#java #object #reference #liskov-substitution-principle
#java #объект #ссылка #принцип подстановки Лискова
Вопрос:
Следующее работает из-за принципа подстановки (Liskov), который гласит, что если ожидается ссылка на экземпляр определенного класса, то вы можете заменить ссылку на экземпляр любого подкласса этого класса.
public static void main( String[] args ) {
Cat felix = new Cat( );
Object copyCat = felix;
}
Теперь, насколько я понимаю, в данном случае я создаю Cat
объект (таким образом, в куче создается пространство памяти), затем я присваиваю объектной переменной ссылки с именем «felix» вновь созданный Cat
объект. Ссылочная переменная имеет тип Cat
, и поэтому может управлять только Cat
и любыми подклассами Cat
.
Затем я создаю Object
ссылочную переменную типа Object
и указываю ее на объект felix ( Cat
), который работает, но с ограниченной функциональностью, поскольку JVM теперь видит, что объект felix имеет тип Object
, поэтому, если бы, например, в purr()
классе был метод, Cat
определенный, felix больше не смог бы его использовать.
Итак, ожидается ссылка на тип Cat
, но мы предоставляем ссылку на суперкласс типа cat (а не на подкласс, как указано в определении выше), и это разрешено, но с ограниченной функциональностью (если вы не выполняете приведение).
Я прав или далек от истины?
Комментарии:
1. Конечно,
felix
мог бы все еще мурлыкать, ноcopyCat
не могу. Память неизменна, но разные типы сообщают компилятору, как смотреть на этот фрагмент памяти.
Ответ №1:
То, что вы делаете, имеет очень мало общего с принципом подстановки Лискова.
Этот принцип является правилом, позволяющим определить, является ли наследование хорошей идеей, или использование наследования является ошибкой. Очевидно, что все объекты наследуются от «Object» : наследование от Object никогда не является ошибкой.
Вот пример, в котором применяется LSP :
Если у вас есть :
abstract class Shape {
abstract public area();
}
class Shape1 extends Shape {
private width;
(...)
}
и
class Shape2 extends Shape {
private width;
private length;
(...)
}
ошибочно думать, что Shape2 наследует Shape1 (помещая атрибут «width» в качестве общего атрибута), потому что метод area () будет отличаться для Shape1 и Shape2.
Ответ №2:
Мне кажется, что вы думаете в терминах ссылок, а не в терминах объектов, и именно поэтому вы переворачиваете определение правила.
Цитирую версию принципа из Википедии:
если S является подтипом T, то объекты типа T могут быть заменены объектами типа S
(которые, похоже, говорят то же самое, что и приведенное вами определение, которое, как я понимаю, взято у вашего преподавателя)
В вашем примере T равно Object
, а S равно Cat
. Когда у вас есть ссылка типа T
Object copyCat;
принцип подстановки гласит, что эта ссылка может указывать на объект типа T или любого типа S, который является подклассом типа T. Таким образом, любое из следующих действий было бы допустимым:
copyCat = new Object();
copyCat = new Cat();
(и поскольку мы используем Object
здесь, который по определению является суперклассом любого класса Java, copyCat
ссылка может указывать на объект любого типа вообще.)
Я думаю, что важным моментом здесь является то, что тип ссылки определяет, какие методы могут быть вызваны, независимо от того, какие методы поддерживает фактический объект, на который указано. Вот почему экземпляр любого подкласса может быть назначен ссылке.
Ответ №3:
В нем говорится, что класс Cat является допустимой заменой класса Object. Так что в любое время, когда какому-либо методу требуется объект типа Object , вы можете заменить объект типа Cat.