Могу ли я в этом случае нарушить ЛСП (подмена Лискова)?

У меня есть абстрактный класс модели, который объявляет список элементов. Аннотация имеет два абстрактных класса. Один, в котором вы можете добавлять новые элементы в список, и другой, который не использует список вообще, но в остальном придерживается другого поведения абстрактного класса модели.

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

Могу ли я в этом случае нарушить LSP (принцип подстановки Лискова)? Или есть способ обойти эту проблему?


person eytanfb    schedule 22.12.2011    source источник
comment
Пожалуйста, покажите нам код. Будет намного понятнее.   -  person JB Nizet    schedule 22.12.2011
comment
Похоже, наследование классов здесь не подходит. Наследование почти всегда имеет смысл только в том случае, если вы можете прозрачно заменить производный класс базовым классом.   -  person helpermethod    schedule 22.12.2011
comment
Нарушение принципа подстановки Лискова почти никогда не является хорошей идеей, поэтому вам понадобится действительно веский аргумент, чтобы оправдать это.   -  person Jesper    schedule 22.12.2011
comment
Просто понял, что отдельные модели мне не нужны. Извините за неприятности. Но я понимаю, почему я не должен нарушать LSP.   -  person eytanfb    schedule 22.12.2011


Ответы (3)


Я думаю, вы нарушите LSP.

Со страницы Википедии для LSP (это всегда ваш друг;):

«Более формально принцип замещения Лискова (LSP) - это конкретное определение отношения подтипов, называемое (сильным) поведенческим подтипом»

«Поведенческий подтип - более сильное понятие, чем типичное подтипирование функций, определенных в теории типов, которая полагается только на контравариантность типов аргументов и ковариантность возвращаемого типа. Поведенческое подтипирование в целом тривиально неразрешимо»

Похоже на ваш случай:

«Типичным примером, нарушающим LSP, является класс Square, производный от класса Rectangle, при условии, что методы получения и установки существуют как для ширины, так и для высоты. Класс Square всегда предполагает, что ширина равна высоте. Если Square объект используется в контексте, где ожидается прямоугольник, может возникнуть непредвиденное поведение, потому что размеры квадрата не могут (или, скорее, не должны) изменяться независимо. Эту проблему нелегко решить: если мы можем изменить методы установки в квадрате класса, чтобы они сохраняли инвариант Square (т. е. сохраняли равные размеры), то эти методы будут ослаблять (нарушать) постусловия для установщиков Rectangle, которые заявляют, что размеры могут быть изменены независимо. Нарушения LSP, подобные этому, могут или может не быть проблемой на практике "

person andrey    schedule 22.12.2011

Никогда не изучал LSP, но я скажу это

Приведение в действие всегда является признаком плохого (менее оптимального) объектно-ориентированного дизайна.

Если вам нужна модель, в которой вы тоже можете настраивать вещи, объявите ее как правильную модель.

то же самое касается API коллекции Java

Collection coll = new ArrayList();
((List) coll).set(3,"sdf");

Код, который будет работать, но просто плохо написан

должно было быть

List coll = new ArrayList();
coll.set(3,"sdf");

используйте конкретный тип для того, что вы хотите

person Peter    schedule 22.12.2011

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

Один класс может расширять только один другой класс. В C ++ этого не было, и в суперклассах могли быть конфликтующие имена. Множественное наследование также породило некоторые проблемы теоретического типа.

Таким образом, вам нужно превратить один аспект в интерфейс и, возможно, перейти от абстрактного класса, реализующего один или несколько интерфейсов.

LSP сохраняется, когда Square расширяется от Rectangle и реализует WidthEqualsHeight.

person Joop Eggen    schedule 22.12.2011