Проще говоря,
LSP касается взаимозаменяемости переменных и ссылок, которые вы используете.Типичным примером является набор api:
ArrayList<String> someList = new ArrayList<>();
Это нормально, но предположим, что у нас есть метод списка:
public void printList(LinkedList<String> printedList) { ... }
Теперь мы не можем передать ArrayList<String>
в *Параметр 1008 *, они разных типов!Однако единственная действительная функциональность, которая нам требуется, - это не специфические особенности LinkedList
или ArrayList
, а скорее только конкретные функции самого List
.Поэтому мы пишем их заменяемыми способами :
List<String> someList = new ArrayList<>(); //still an arraylist!
public void printList(List<String> printedList) { ... } //any list type
Теперь мы можем передать наш параметр, так как мы не связаны без необходимости с подтипом, для которого нам не требуется функциональность.
С точки зрения уровня памяти эти объекты все еще являются одними и теми же объектами в динамической памяти, вы просто называете их супертипом (и на самом деле вы можете уменьшить их, если знаете тип).
Итак, используя ваш пример, у вас может быть случай, когда любое существующее транспортное средство имеет цвет.Итак, у нас есть методы:
public class Vehicle {
public Color getColor() { ... }
public void setColor(Color color) { ... }
}
И при этом любой подкласс для Vehicle
будет иметь цветовые методы, но не более специфические методы, скажем, BMW
или Car
.Однако это больше относится к наследованию, чем LSP.