Child object 通过抽象 class 类型变量或 child class 类型变量引用?

Child object reference by abstract class type variable or child class type variable?

抱歉,我的标题很混乱,我自己也有点困惑,所以我只举个例子:D 假设我们有:

public abstract class Vehicle {
    public abstract void paint();
}
public class Car extends Vehicle {
    public void paint() {
        ...
    }
    public void sell() {
        ...
    }
}
  1. 类型车
Car c = new Car();
c.paint();
c.sell(); //works
  1. 类型车辆
Vehicle c = new Car();
c.paint();
c.sell(); //error

那么使用后一种格式有什么意义呢?我只能想到 restriction/privacy 但即便如此也想不出一个合理的例子。哪个选项更适合用作一般做法?

我不是专家,但据我所知

后一种格式用于实现抽象,即隐藏函数的内部工作。

现在的实施取决于 class 扩展您的 Vehicle class(这里是 Car)。 这让您可以自由地实现绘画功能,而不必担心 class 正在实现它。

例如:

Bike extends Vehicle {
// body
}

现在你实施

Vehicle.paint() 根据您的配置,您可以涂装自行车或汽车。用得好还是很给力的

使用 interface 也很好,因为它强制 java 使用空方法。

如果您想知道错误原因,那是因为 Vechicle 不知道函数 sell 存在,因为它是由 class Car 定义的,而不是Vechicle,但 paint() 将像 运行 Car.paint().

一样工作

超级class意味着你在某些class之间有一些共同点,这些共同点可能是属性或method.abstract

class 表示您有一些概念,可能需要其子class.

完成一些方法实现

你可能在你的应用程序的某个地方需要vehicle概念,不管它是什么车辆,给车辆上色,所以,你只需要知道传递的参数是车辆。

这两个概念都是对的,但是要看你的用法和你的设计。

如果您只需要车辆概念而不考虑其子类型,则必须使用第二个,在这种情况下您需要使用方法 sell()您必须使用第一个,因为您提供了该方法它的属性来自定义部分,而不是实例化部分。

最后学习一下OOP中的Abstraction,它可能对你更有帮助。希望对您有所帮助:)

接口的思想是有不同的类实现接口,调用者不需要知道(或关心)它是哪一个。

再比如,拿Java的OutputStream. It's an abstract class (so a bit more "meat" or logic than a real interface), but the main idea is the same. In your program you can write to an OutputStream that the caller passes in. You just take care of writing what you have to write. The caller on the other hand can decide on what needs to be done with the data you write: send it over the network or save it to a file or pipe it into another program? Zip it or encrypt呢?调用者可以通过向您传递一个不同的 OutputStream 来做到这一点,并且您的代码不需要更改来处理网络 I/O、压缩或加密。

测试可以通过 ByteArrayOutputStream 来捕获程序的输出。

Vehicle c = new Car();
c.paint(); // <- THIS is the point of the latter format.

这种格式的要点是能够调用 paint,即使您不知道 Vehicle 正在绘制的是什么类型。

假设您有 ArrayListVehicle 需要涂漆。

ArrayList<Vehicles> vehicles = new ArrayList<>();

vehicles.add(new Car());
vehicles.add(new Jet());
vehicles.add(new Tank());

for(Vehicle vehicle : vehicles) {
    vehicle.paint(); // <- This is the power, right here.
}

您肯定 不会 在该循环内调用 sell 方法,因为它仅适用于 Cars(根据您的设计) , 而不是所有 Vehicles.