Java不允许Collection<Car>
作为Collection<Vehicle>
的子类型。这是因为Collection<Car>
不能用于代替每个Collection<Vehicle>
,因为Collection<Vehicle>
可能包含其他子类型的元素,例如摩托车,因此它违反了Liskov替换原则?
答案 0 :(得分:1)
通常,由于存在“可选操作”,Collection
违反了Liskov替换原则,即突变方法可能无法用于特定实现。
关于类型安全性,它的工作原理如下:
假设Car
是Vehicle
的子类型,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>