Является ли определение моего лектора принципа замещения Лисков неверным, или я неправильно понимаю?

Следующее работает из-за принципа подстановки (Лисков), который гласит, что если ожидается ссылка на экземпляр определенного класса, то вы можете заменить ссылку на экземпляр любого подкласса этого класса.

public static void main( String[] args ) {
Cat felix = new Cat( );
Object copyCat = felix;
}

Теперь, насколько я понимаю, в этом случае я создаю объект Cat (поэтому в куче создается пространство памяти), затем я присваиваю вновь созданному объекту Cat переменную ссылки на объект с именем "felix". Ссылочная переменная имеет тип Cat, поэтому может управлять только Cat и любыми подклассами Cat.

Затем я создаю ссылочную переменную Object типа Object и указываю ее на объект felix (Cat), который работает, но с ограниченной функциональностью, поскольку JVM теперь видит объект felix типа Object, поэтому, если, например, был метод purr(), определенный в классе Cat, Феликс больше не сможет его использовать.

Таким образом, ожидается ссылка типа Cat, но мы предоставляем ссылку на суперкласс типа cat (а не на подкласс, как сказано в определении выше), и это разрешено, но с ограниченной функциональностью (если вы не сделаете В ролях).

Я прав или отклоняюсь?


person Albatross32    schedule 19.04.2011    source источник
comment
Конечно, felix еще может мурлыкать, а copyCat нет. Память не меняется, но разные типы сообщают компилятору, как смотреть на этот участок памяти.   -  person DarkDust    schedule 19.04.2011


Ответы (3)


То, что вы делаете, имеет очень мало общего с принципом замещения Лискова.

Этот принцип является правилом, позволяющим узнать, является ли наследование хорошей идеей или его использование является ошибкой. Очевидно, что каждый объект наследуется от "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 (с указанием атрибута «ширина» в качестве общего атрибута), потому что метод area() будет отличаться для Shape1 и Shape2.

person Tristan    schedule 19.04.2011

Мне кажется, что вы мыслите в терминах ссылок, а не в терминах объектов, и поэтому вы инвертируете определение правила.

Цитируя версию принципа из Википедии:

если S является подтипом T, то объекты типа T могут быть заменены объектами типа S

(которые, кажется, говорят то же самое, что и определение, которое вы предоставили, которое, как я понимаю, от вашего инструктора)

В вашем примере T равно Object, а S равно Cat. Когда у вас есть ссылка типа T

Object copyCat;

что говорит принцип подстановки, так это то, что эта ссылка может указывать на объект типа T или любого типа S, который является подклассом типа T. Таким образом, любое из следующего будет допустимым:

copyCat = new Object();
copyCat = new Cat();

(и поскольку мы используем здесь Object, который по определению является суперклассом любого класса Java, ссылка copyCat может указывать на любой тип объекта вообще.)

Я думаю, что важным моментом здесь является то, что тип ссылки определяет, какие методы могут быть вызваны, независимо от того, какие методы поддерживает фактический объект. Вот почему экземпляр любого подкласса может быть назначен ссылке.

person Dave Costa    schedule 19.04.2011

Это говорит о том, что класс Cat является допустимой заменой класса Object. Так что в любое время, когда какому-то методу понадобится объект типа Object, вы можете заменить его объектом типа Cat.

person MeBigFatGuy    schedule 19.04.2011