Java does not permit Collection<Car> as a subtype of Collection<Vehicle>. Is this because Collection<Car> cannot be used in place of every Collection<Vehicle> as the Collection<Vehicle> could contain elements which are other subtypes of Vehicle such as Motorbike, therefore it violates Liskov substitution principle?
4 回答
通常,Collection由于“可选操作”的存在,s 违反了 Liskov 替换原则,即变异方法可能无法用于特定的实现。
然而,关于类型安全,它是这样工作的:
假设它Car是 的子类型Vehicle,aCollection<Car>是允许类似操作的类型
Collection<Car> c=…;
Car car=c.iterator().next();
Collection<Vehicle>没有。另一方面,Collection<Vehicle>是一种允许类似操作的类型
Collection<Vehicle> c=…;
Vehicle v=…;
c.add(v);
Collection<Car>没有。因此,这些Collection类型都不是另一个的子类型。
Collection<T>是类型构造函数,因此Collection<Car>是类型并且Collection<Vehicle>是另一种类型。
现在的问题是,如果 aCollection<Car>可以在Collection<Vehicle>需要 a 的地方使用,那就是方差问题(这种情况是协方差)。
Liskov 替换原则以某种方式超越了类型一致性,它不仅要求提供更多,要求更少,而且还保留了超类型的合同,请参阅 Wikipedia。
请注意, a在组件类型上Collection<Car>是不变Car的。因此,如果您想使用可能是汽车、自行车、火车等的车辆集合,您应该使用协变集合Collection<? extends Vehicle>。
当然,如果你有CarFactory一个生产方法,应该将生产的汽车停在某个地方,那么逆变 produce(Collection<? super Car>)方法将是最有用的实现。
不完全是。另一种方式:
aCollection<Car>只包含Cars 很好,即使 aCollection<Vehicle>可能包含其他类型的车辆。您仍然可以将 a 提供Collection<Car>给任何可以处理 a 中的元素的人Collection<Vehicle>。
但Collection<Car>不能用于代替 a Collection<Vehicle>,因为您可以将 aBicycle放入 a Collection<Vehicle>(但不能放入 a Collection<Car>)。所以你不能把它Collection<Car>交给想要收集车辆的人。