class Vehicle {
Engine myEngine = new Engine();
void start() {
myEngine.start();
}
void stop() {
myEngine.stop();
}
}
class VehicleWithSteering extends Vehicle {
Steering mySteering = new Steering();
void start() {
mySteering.reset();
myEngine.start();
}
void steerLeft() {
mySteering.left();
}
void steerRight() {
mySteering.right();
}
}
如您所见,VehicleWithSteering 确实有基本的Vehicle 没有的方法。它还覆盖了void start() 方法,因为启动这个更复杂的车辆涉及不同的例程。
class NoviceDriver {
Vehicle myVehicle;
public NoviceDriver(Vehicle vehicle) {
myVehicle = vehicle;
}
void doSomething() {
myVehicle.start();
myVehicle.stop();
}
}
class AdvancedDriver {
VehicleWithSteering myVehicle;
public NoviceDriver(VehicleWithSteering vehicle) {
myVehicle = vehicle;
}
void doSomethingElse() {
myVehicle.start();
myVehicle.steerLeft();
myVehicle.stop();
}
}
AdvancedDriver 需要基本Vehicle 无法满足的附加功能,因此它始终需要VehicleWithSteering 的实例。
class Test{
public static void main(String[] args) {
// Create one basic vehicle
Vehicle a = new Vehicle();
// And one more advanced
VehicleWithSteering b = new VehicleWithSteering();
// A novice driver is satisfied with having a basic vehicle
NoviceDriver x = new NoviceDriver(a);
// The advanced driver however needs more functionality
AdvancedDriver y = new AdvancedDriver(b);
// A novice driver can use the advanced vehicle as well
// But he will not bother about the advanced functionality
NoviceDriver z = new NoviceDriver(b);
}
}
NoviceDriver 只知道如何访问Vehicle 的方法。但由于VehicleWithSteering 中也存在这些方法,因此他也可以使用该方法。 NoviceDriver 甚至不知道转向意味着什么,所以他不会触摸任何他不知道的控件。
AdvancedDriver 不能与 Vehicle 配合使用,因为它不包含所需的转向方法。
如果对 VehicleWithSteering 进行更高级的改进,NoviceDriver 和 AdvancedDriver 仍然可以使用它来执行其有限的任务,因为它仍然提供所需的基本功能。
NoviceDriver 可以访问原始Vehicle 拥有的所有公共方法和属性。它不知道以后添加的新方法或属性。在这种情况下,它可以看到VehicleWithSteering 上继承的Engine myEngine 属性,但看不到新的Steering mySteering 属性。
至于你的最后一个问题:这取决于语言。
在 Java 中,每个类都有一个其他继承类和它实现的接口的内部列表。每当您将细化转换为更原始的类型时,Java 都会检查原始类型是否在列表中。这种行为也用于其他严格类型的语言,例如 C++、C# 和许多其他语言。
另一种概念是 Duck-Typing。
当我看到一只像鸭子一样走路,像鸭子一样游泳,像鸭子一样叫的鸟时,我称那只鸟为鸭子。
当一种语言使用 Duck-Typing 时,它会通过名称和签名在对象中查找请求的方法。这可能发生在编译时或运行时,在后一种情况下,大多数支持 Duck-Typing 的语言都会引发异常。
一些语言,如 PHP 和其他各种脚本语言都具有严格的类型检查和 Duck-Typing。这意味着您既可以选择对继承的类列表和实现的接口强制执行严格的类型检查,也可以在省略该检查时默认使用 Duck-Typing。