我车库里真的有车吗? [英] Do I really have a car in my garage?

查看:60
本文介绍了我车库里真的有车吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Java编程的新手,试图掌握OOP。

I'm a newbie to Java programming, trying to get the hang of OOP.

所以我构建了这个抽象类:

So I built this abstract class:

public abstract class Vehicle{....}

和2个子类:

public class Car extends Vehicle{....}
public class Boat extends Vehicle{....}

汽车 Boat 还包含一些不常见的唯一字段和方法(不具有相同的名称,因此我无法为它们定义抽象方法)车辆)。

Car and Boat also hold some unique fields and methods that aren't common (don't have the same name, so I can't define an abstract method for them in Vehicle).

现在在mainClass我设置了我的新车库:

Now in mainClass I have setup my new Garage:

Vehicle[] myGarage= new Vehicle[10];
myGarage[0]=new Car(2,true);
myGarage[1]=new Boat(4,600);

我对多态性感到非常满意,直到我尝试访问Car独有的字段之一,例如:

I was very happy with polymorphism until I tried to access one of the fields that are unique to Car, such as:

boolean carIsAutomatic = myGarage[0].auto;

编译器不接受。我使用强制转换解决了这个问题:

The compiler doesn't accept that. I worked around this issue using casting:

boolean carIsAutomatic = ((Car)myGarage[0]).auto;

这有效......但它对方法没有帮助,只是字段。意思是我做不到

That works... but it doesn't help with methods, just fields. Meaning I can't do

(Car)myGarage[0].doSomeCarStuff();

所以我的问题是 - 我的车库里到底有什么?我试图获得直觉以及了解幕后发生了什么。

So my question is - what do I really have in my garage? I'm trying to get the intuition as well as understand what's going on "behind the scenes".

为了这个缘故未来的读者,以下答案的简短摘要:

for the sake of future readers, a short summary of the answers below:


  1. 是的,有一个汽车 in myGarage []

  2. 作为一种静态类型语言,Java编译器不会提供对非方法/字段的访问权限 - 车辆,如果通过基于Vehicle超级类的数据结构访问它们(例如 Vehicle myGarage []

  3. 至于如何解决,有以下两种主要方法:
  1. Yes, there's a Car in myGarage[]
  2. Being a static typed language, the Java compiler will not lend access to methods/fields that are non-"Vehicle", if accessing those through a data structure based on the Vehicle super class( such as Vehicle myGarage[])
  3. As for how to solve, there are 2 main approaches below:

  1. 使用类型转换,这将减轻编译器的顾虑并将设计中的任何错误留给运行时间

  2. 我需要铸造的事实说设计存在缺陷。如果我需要访问非车辆功能,那么我不应该将汽车和船只存储在基于车辆的数据结构中。要么使所有这些功能属于Vehicle,要么使用更具体(派生)类型的结构


  • 在许多情况下,组合和/或接口将是继承的更好替代方案。可能是我下一个问题的主题...

  • 如果有人有时间浏览答案,还有很多其他好的见解。


  • 推荐答案

    如果你需要区分 Car ,那么你应该将它们存放在不同的结构中。

    If you need to make the difference between Car and Boat in your garage, then you should store them in distinct structures.

    例如:

    public class Garage {
        private List<Car> cars;
        private List<Boat> boats;
    }
    

    然后,您可以定义特定于船只或特定于汽车的方法。

    Then you can define methods that are specific on boats or specific on cars.

    假设车辆如下:

    public abstract class Vehicle {
       protected int price;
       public getPrice() { return price; }
       public abstract int getPriceAfterYears(int years);
    }
    

    每个车辆有一个价格,所以它可以放在 Vehicle 抽象类中。

    Every Vehicle has a price so it can be put inside the Vehicle abstract class.

    然而,确定n后价格的公式几年取决于车辆,所以它留给实施班来定义它。例如:

    Yet, the formula determining the price after n years depends on the vehicle, so it left to the implementing class to define it. For instance:

    public Car extends Vehicle {
        // car specific
        private boolean automatic;
        @Override
        public getPriceAfterYears(int years) {
            // losing 1000$ every year
            return Math.max(0, this.price - (years * 1000));  
        }
    }
    

    class可能有 getPriceAfterYears 的其他定义以及特定的属性和方法。

    The Boat class may have an other definition for getPriceAfterYears and specific attributes and methods.

    所以现在回到 Garage 类,你可以定义:

    So now back in the Garage class, you can define:

    // car specific
    public int numberOfAutomaticCars() {
        int s = 0;
        for(Car car : cars) {
            if(car.isAutomatic()) {
                s++;
            }
        }
        return s;
    }
    public List<Vehicle> getVehicles() {
        List<Vehicle> v = new ArrayList<>(); // init with sum
        v.addAll(cars);
        v.addAll(boats);
        return v;
    }
    // all vehicles method
    public getAveragePriceAfterYears(int years) {
        List<Vehicle> vehicules = getVehicles();
        int s = 0;
        for(Vehicle v : vehicules) {
            // call the implementation of the actual type!
            s += v.getPriceAfterYears(years);  
        }
        return s / vehicules.size();
    }
    

    多态的兴趣是能够调用 getPriceAfterYears 车辆 没有关心实施。

    The interest of polymorphism is to be able to call getPriceAfterYears on a Vehicle without caring about the implementation.

    通常,向下转向是设计有缺陷的标志:如果您需要区分其实际类型,请不要将您的车辆全部存放在一起。

    Usually, downcasting is a sign of a flawed design: do not store your vehicles all together if you need to differenciate their actual type.

    注意:当然是设计这里可以轻松改进。这只是一个展示要点的例子。

    Note: of course the design here can be easily improved. It is just an example to demonstrate the points.

    这篇关于我车库里真的有车吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆