集合子类型 - Liskov替换原则

时间:2015-04-22 10:40:49

标签: java collections liskov-substitution-principle subtyping

Java不允许Collection<Car>作为Collection<Vehicle>的子类型。这是因为Collection<Car>不能用于代替每个Collection<Vehicle>,因为Collection<Vehicle>可能包含其他子类型的元素,例如摩托车,因此它违反了Liskov替换原则?

4 个答案:

答案 0 :(得分:1)

通常,由于存在“可选操作”,Collection违反了Liskov替换原则,即突变方法可能无法用于特定实现。

关于类型安全性,它的工作原理如下:

假设CarVehicle的子类型,Collection<Car>是允许类似

的操作的类型
Collection<Car> c=…;
Car car=c.iterator().next();

Collection<Vehicle>没有。另一方面,Collection<Vehicle>是一种允许像

这样的操作的类型
Collection<Vehicle> c=…;
Vehicle v=…;
c.add(v);

Collection<Car>没有。因此,这些Collection类型都不是另一种类型的子类型。

答案 1 :(得分:0)

不完全是。反过来说:

即使Collection<Car>可能包含其他类型的车辆,Car只包含Collection<Vehicle>也没关系。您仍然可以向能够处理Collection<Car>元素的任何人提供Collection<Vehicle>

Collection<Car>不能代替Collection<Vehicle>,因为您可以将Bicycle放入Collection<Vehicle>(但不能放在Collection<Car>中) 。因此,您无法将Collection<Car>提供给想要收集车辆的人。

答案 2 :(得分:0)

Collection<T>是一种类型构造函数,因此Collection<Car>是一种类型,Collection<Vehicle>是另一种类型。

现在的问题是,如果Collection<Car>可以在需要Collection<Vehicle>的情况下使用,则是一个方差问题(这种情况下是协方差)。

Liskov替换原则超出了类型一致性,它不仅要求提供更多,更少需要,而且还要保留超类型的契约,see Wikipedia

答案 3 :(得分:0)

请注意,组件类型Collection<Car>上的Car 不变。因此,如果您想使用可能是汽车,自行车,火车等车辆的集合,您应该使用协变集合Collection<? extends Vehicle>

当然,如果你有CarFactory生产方法应该将生产的汽车停放在某个地方,那么逆变 produce(Collection<? super Car>)方法将是最有用的实施方案。< / p>

相关问题