Ява не разрешает Collection<Car>
как подтип Collection<Vehicle>
. Это потому, что Collection<Car>
не может использоваться вместо каждого Collection<Vehicle>
, поскольку Collection<Vehicle>
может содержать элементы, которые являются другими подтипами транспортного средства, такие как мотоцикл, поэтому он нарушает принцип замещения Лискова?Подтипы коллекций - Лисков Замена Принцип
ответ
Не совсем. В противоположном случае:
Что касается Collection<Car>
, то содержит только Car
. S в порядке, хотя Collection<Vehicle>
может содержать другие типы транспортных средств. Вы все равно можете дать Collection<Car>
всем, кто может обрабатывать элементы из Collection<Vehicle>
.
Но Collection<Car>
не может использоваться вместо Collection<Vehicle>
, потому что вы могли бы поставить Bicycle
в Collection<Vehicle>
(но не в Collection<Car>
). Поэтому вы не можете дать Collection<Car>
тем, кто хочет собирать автомобили.
В целом, Collection
нарушает принцип замещения Лискова из-за существования «необязательных операций», то есть методы мутации могут быть непригодными для конкретной реализации.
Что касается безопасности типа, однако, она работает таким образом:
Если предположить, что 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
не является подтипом другого.
См. Http://stackoverflow.com/questions/22050848/do-collections-unmodifiablexxx-methods-violate-lsp для обсуждения о том, нарушают ли методы мутации коллекции методы LSP. – jaco0646
Collection<T>
является конструктором типа, поэтому Collection<Car>
является типом и Collection<Vehicle>
- это другой тип.
Теперь вопрос, если требуется Collection<Car>
, где требуется Collection<Vehicle>
, является вопросом дисперсии (сопутствующий случай - это случай).
Принцип замены Лискова превосходит тип соответствия таким образом, что он не только требует большего, требует меньше, но также и того, что договор супертипа сохраняется, see Wikipedia.
Отметьте, что Collection<Car>
является неизменным над состоянием типа Car
. Поэтому, если вы хотите использовать коллекцию транспортных средств, которые могут быть автомобилями, велосипедами, поездами и т. Д., Вы должны взять ковариантCollection<? extends Vehicle>
.
Конечно, если у вас есть CarFactory
с методом продукции, который должен парковать произведенные машины где-то, контравариантенproduce(Collection<? super Car>)
метод будет наиболее полезным выполнением.
Это больше связано с проблемой инвариантности при использовании дженериков и ковариантного ответа, который идет с ним. – alainlompo