Java 集合子类型-Liskov替换原则
Java不允许将Java 集合子类型-Liskov替换原则,java,collections,liskov-substitution-principle,subtyping,Java,Collections,Liskov Substitution Principle,Subtyping,Java不允许将Collection作为Collection的子类型。这是因为集合不能代替每个集合,因为集合可能包含其他车辆子类型的元素,如摩托车,因此它违反了Liskov替换原则?不完全如此。反过来说: 即使集合可能包含其他类型的车辆,但集合仅包含汽车s也可以。您仍然可以将集合提供给任何可以处理集合中元素的人 但是集合不能代替集合,因为可以将自行车放入集合(但不能放入集合)。因此,您不能将收集提供给想要收集车辆的人。通常,收集由于存在“可选操作”,因此违反了Liskov替换原则,即变异方法可能
Collection
作为Collection
的子类型。这是因为集合
不能代替每个集合
,因为集合
可能包含其他车辆子类型的元素,如摩托车,因此它违反了Liskov替换原则?不完全如此。反过来说:
即使集合
可能包含其他类型的车辆,但集合
仅包含汽车
s也可以。您仍然可以将集合
提供给任何可以处理集合
中元素的人
但是
集合
不能代替集合
,因为可以将自行车
放入集合
(但不能放入集合
)。因此,您不能将收集
提供给想要收集车辆的人。通常,收集
由于存在“可选操作”,因此违反了Liskov替换原则,即变异方法可能无法用于特定实现
但是,就类型安全而言,它是这样工作的:
假设Car
是Vehicle
的一个子类型,则集合
是一种允许以下操作的类型
Collection<Car> c=…;
Car car=c.iterator().next();
Collection<Vehicle> c=…;
Vehicle v=…;
c.add(v);
集合c=…;
Car-Car=c.iterator().next();
哪个集合
没有。另一方面,Collection
是一种允许执行以下操作的类型
Collection<Car> c=…;
Car car=c.iterator().next();
Collection<Vehicle> c=…;
Vehicle v=…;
c.add(v);
集合c=…;
车辆v=…;
c、 添加(v);
哪个集合
没有。因此,这两种Collection
类型都不是另一种类型的子类型。Collection
是类型构造函数,因此Collection
是一种类型,Collection
是另一种类型
现在的问题是,如果集合
可以用于需要集合
的地方,那么这是一个方差问题(这种情况下是协方差)
Liskov替代原则在某种程度上超越了类型一致性,它不仅要求提供更多,要求更少,而且还要求保持超类型的契约。请注意,
集合
在组件类型汽车
上是不变的。因此,如果你想使用汽车、自行车、火车等车辆的集合,你应该使用协变集合collection这与使用泛型的不变性挑战和协变响应更相关,请参见关于集合变异方法是否违反LSP的辩论。