LINUX.ORG.RU

Вопрос по принципу Лисков.

 ,


0

3

Возьмем классический пример, когда принцип подстановки Лисков не может быть реализован. Точней так считает большинство. Пример квадрата как подкласса прямоугольника.

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

Контракт прямоугольника (инвариант): ширина и высота положительны.

Контракт квадрата (инвариант): ширина и высота положительны; ширина и высота равны.

допустим, мы переопределяем методы квадрата setWidth и setHeight таким образом, что квадрат не реагирует на них, просто игнорирует.

Нарушили ли мы контракты? Нет. Нарушили ли мы принцип Лисков? Да, вроде, тоже нет. Тогда в чем проблема?

Дата регистрации: 28.11.2016 13:43:35

Опять анонiмус со своими Гидралисками пришёл.

EXL ★★★★★
()
Ответ на: комментарий от Alve

этож анонiiмус он всегда разговаривает с метафизической общностью лора

Deleted
()
Ответ на: комментарий от linearisation

Для обьекта прямоугольник я мог задать ширину путем вызова метода setWidth, для квадрата, как его описал ты, не могу задать ширину вызовом этого метода, т.е. я не могу использовать объект квадрат, где раньше использовался прямоугольник.

goingUp ★★★★★
()

допустим, мы переопределяем методы квадрата setWidth и setHeight таким образом, что квадрат не реагирует на них, просто игнорирует.

Нарушили ли мы контракты? Нет.

Афигеть.

tailgunner ★★★★★
()

Контракт прямоугольника (инвариант): ширина и высота положительны.

Стороны не отрицательны :-)

Контракт квадрата (инвариант): ширина и высота положительны; ширина и высота равны.

Стороны равны :-) (Вырожденный случай - точка) :-)

допустим, мы переопределяем методы квадрата setWidth и setHeight таким образом, что квадрат не реагирует на них, просто игнорирует.

Игнорить нельзя, выше ты определил ОДЗ, т.е. инварианты :-) Нарушение инвариантов - это логическая ошибка :-)

Нарушили ли мы контракты? Нет. Нарушили ли мы принцип Лисков? Да, вроде, тоже нет. Тогда в чем проблема?

Нет проблем :-)

anonymous
()
Ответ на: комментарий от goingUp

Для обьекта прямоугольник я мог задать ширину путем вызова метода setWidth, для квадрата, как его описал ты, не могу задать ширину вызовом этого метода

А разве это есть в наших контрактах, что изменения гарантируются для любого вызова?

linearisation
() автор топика
Ответ на: комментарий от linearisation

Согласно твоим контрактам объекты можно инициализировать со сторонами 1 и 1 и вообще никакие методы не нужны.

goingUp ★★★★★
()
Ответ на: комментарий от linearisation

Что то я не вижу в каком месте они нарушаются

У квадрата стороны равны :-) Поэтому, если имеется ссылка на объект прямоугольника (общий случай квадрата), когда на самом деле это квадрат, должна сработать проверка ОДЗ для квадрата :-)

anonymous
()
Ответ на: комментарий от goingUp

вообще никакие методы не нужны.

А как же изменения сторон прямоугольника? Ты это к чему вообще?

linearisation
() автор топика
Ответ на: комментарий от anonymous

Поэтому, если имеется ссылка на объект прямоугольника (общий случай квадрата), когда на самом деле это квадрат, должна сработать проверка ОДЗ для квадрата :-)

Если мы обращаемся к квадрату как к прямоугольнику, почему нас должны интересовать квадрат это или не квадрат?

linearisation
() автор топика

допустим, мы переопределяем методы квадрата setWidth и setHeight таким образом, что квадрат не реагирует на них, просто игнорирует.

Допустим мы выносим эти методы в отдельный интерфейс, который квадрат ес-но не будет реализовывать.

anonymous
()
Ответ на: комментарий от anonymous

много что можно сделать, чтобы не работало, но это отношения к делу, по-моему, не имеет

linearisation
() автор топика
Ответ на: комментарий от linearisation

Если мы обращаемся к квадрату как к прямоугольнику, почему нас должны интересовать квадрат это или не квадрат?

Кого нас? :-) Инвариант должен не нарушаться, только и всего :-) С другой стороны, нет основания игнорить вызов метода :-) Логичнее уж определить для квадрата setX и setY одинаково :-)

anonymous
()
Ответ на: комментарий от goingUp

У прямоугольника ведь, помимо этого мало ли что еще может быть, например, метод масштабирования, который вполне применим и к частному случаю, если ты о мнимой «бессмысленности»

linearisation
() автор топика

Превратили программирование чёрт знает во что.

ilovewindows ★★★★★
()
Ответ на: комментарий от anonymous

Ну, то есть, не нарушается тут принцип Лисков, это гон, правильно? Нет непреодолимых препятствий для того, чтобы реализовать его в данном случае, правильно?

linearisation
() автор топика
Ответ на: комментарий от linearisation

Ты хочешь сказать, что в мире есть второй человек, обожающий JS и модель акторов, и при этом испытывающий анальный зуд при виде слова Haskell?

hateyoufeel ★★★★★
()
Ответ на: комментарий от linearisation

Ну, то есть, не нарушается тут принцип Лисков, это гон, правильно? Нет непреодолимых препятствий для того, чтобы реализовать его в данном случае, правильно?

Зацепила тебя Барбара :-) В данном конкретном случае нарушений не видно :-)

anonymous
()

Поставьте, пожалуйста, тег «парадигма». Такие посты не воспринимаются серьезно без этого слова. Обязательно должно быть!

Zubok ★★★★★
()
Ответ на: комментарий от anonymous

Не то чтобы зацепило, просто пришла вголову такая мысль. В целом мне насрать и на нее и на SOLID в целом, это все ереси, к нормальному ООП в кеевском смысле это едва ли имеет какое то отношение. В некоторых случаях может быть полезно, но не более того.

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

linearisation
() автор топика
Ответ на: комментарий от linearisation

В целом мне насрать и на нее и на SOLID в целом, это все ереси, к нормальному ООП в кеевском смысле это едва ли имеет какое то отношение.

Ну, типа, если этого принципа придерживаться, то в рантайме проверок будет меньше :-)

В рассматриваемом случае, я бы скорей всего просто удалил данные методы из квадрата, скорей всего.

Честно говоря, квадрат - это не прямоугольник, у которого все стороны равны :-) Квадрат - это _правильный_ четырёхугольник :-) Другими словами, интерфейсы у них разные :-) У квадрата лишь один метод, какой-нибудь setLength, тогда как у прямоугольника их два :-)

anonymous
()
Ответ на: комментарий от anonymous

Честно говоря, квадрат - это не прямоугольник, у которого все стороны равны :-) Квадрат - это _правильный_ четырёхугольник :-) Другими словами, интерфейсы у них разные :-) У квадрата лишь один метод, какой-нибудь setLength, тогда как у прямоугольника их два :-)

Но сделать квадрат наследником прямоугольника все же имеет смысл, с точки зрения совместного использования кода и быстрого внесения общих изменений так как общего у них все же гораздо больше. В прямоугольнике еще хз сколько может быть совместимых методов, масштабирование, растягивание и тп

linearisation
() автор топика

Пример квадрата как подкласса прямоугольника.

Не определяй квадрат как подкласс прямоугольника.

i-rinat ★★★★★
()
Ответ на: комментарий от linearisation

Но сделать квадрат наследником прямоугольника все же имеет смысл, с точки зрения совместного использования кода и быстрого внесения общих изменений так как общего у них все же гораздо больше. В прямоугольнике еще хз сколько может быть совместимых методов, масштабирование, растягивание и тп

Тогда уж имеет смысл сущность «Многоугольник» с методами «являетсяПравильным?», «количествоСторон», «уголМеждуСторонами» и т.д. :-) Нафиг тут какие-то принципы подстановок? :-)

anonymous
()

анонiмус предсказуем, его даже движок ЛОРа распознает в похожих темах.

winlook38 ★★
()
Ответ на: комментарий от anonymous

Принципы подстановки тут не причем, это так, к слову:)

linearisation
() автор топика
Ответ на: комментарий от linearisation

Можно себе представить класс «прямоугольник с заданным соотношением длин сторон», у которого метод setwidth меняет не только ширину, но и высоту. Квадрат это такой прямоугольник с соотношением 1:1. Но если контракт метода setwidth не позволяет менять ничего, кроме ширины, то такой прямоугольник не является прямоугольником.

Если прямоугольник не содержит методов setwidth/setheight, а содержит только getwidth/getheight, то квадрат является прямоугольником.

iliyap ★★★★★
()
Ответ на: комментарий от EXL

Надо поставить тест при регистрации - какая нибудь заумная концепция программирования и заведомо правильный ответ будет означать провал. Большинство кликнет на произвольный вариант, и лишь анонiмус будет тыкать правильные ответы и не попадет на ЛОР :)

I-Love-Microsoft ★★★★★
()

Хм, надо этим кандидатов на собеседовании развлекать.

Pavval ★★★★★
()

допустим, мы переопределяем методы квадрата setWidth и setHeight таким образом, что квадрат не реагирует на них, просто игнорирует.

Нарушили ли мы контракты? Нет. Нарушили ли мы принцип Лисков? Да, вроде, тоже нет.

У прямоугольника есть свойство - если ему сначала установить ширину в N условных единиц, а затем запросить у него ширину, то мы получим обратно эти N условных единиц. То же самое и с длиной. При этом изменение ширины не затрагивает длину, и наоборот. Вот тут-то твой пример сосёт.

Вот псевдокод для примера:

RSpec.shared_examples 'rectangle' do
  describe '#width=' do
    it 'changes #width' do
      new_width = subject.width + 1
      subject.width = new_width
      expect(subject.width).to eq(new_width)
    end

    it "doesn't change #height" do
      expect { subject.width += 1 }.not_to change { subject.height }
    end
  end

  describe '#height=' do
    it 'changes #height' do
      new_height = subject.height + 1
      subject.height = new_height
      expect(subject.height).to eq(new_height)
    end

    it "doesn't change #width" do
      expect { subject.height += 1 }.not_to change { subject.width }
    end
  end
end

RSpec.describe Rectangle do
  subject { described_class.new(width: 3, height: 4) }
  it_behaves_like 'rectangle'
end

RSpec.describe Square do
  subject { described_class.new(3) }
  it_behaves_like 'rectangle' # FAIL!
end

# $ rspec rect.rb
# ....F.F.
#
# Failures:
#
#   1) Square behaves like rectangle #width= changes #width
#      Failure/Error: expect(subject.width).to eq(new_width)
#
#        expected: 4
#             got: 3
#
#        (compared using ==)
#      Shared Example Group: "rectangle" called from ./rect.rb:80
#      # ./rect.rb:51:in `block (3 levels) in <top (required)>'
#
#   2) Square behaves like rectangle #height= changes #height
#      Failure/Error: expect(subject.height).to eq(new_height)
#
#        expected: 4
#             got: 3
#
#        (compared using ==)
#      Shared Example Group: "rectangle" called from ./rect.rb:80
#      # ./rect.rb:63:in `block (3 levels) in <top (required)>'
#
# Finished in 0.05544 seconds (files took 0.2406 seconds to load)
# 8 examples, 2 failures
#
# Failed examples:
#
# rspec './rect.rb[2:1:1:1]' # Square behaves like rectangle #width= changes #width
# rspec './rect.rb[2:1:2:1]' # Square behaves like rectangle #height= changes #height
theNamelessOne ★★★★★
()
Ответ на: комментарий от theNamelessOne

Аплодисменты безымянному!

anonymous
()

На самом деле квадрат это правильный многоугольник, а не прямоугольник. У него есть свойства: Расстояние от центра до угла и количество сторон. Собссно шести-, восьми-, двенадцати-, стосорокажести- угольники - это родственники квадрата. Круг, кстати, тоже. У него просто количество сторон длизкое к бесконечности.

Прямоугольник в это не вписывается, так как у него есть 2 длины, как минимум.

anonymous
()
Ответ на: комментарий от anonymous

На самом деле квадрат это правильный многоугольник, а не прямоугольник.

Да? Ничего себе!

anonymous
()

Нарушили ли мы контракты? Нет. Нарушили ли мы принцип Лисков? Да, вроде, тоже нет. Тогда в чем проблема?

Тебе контракты чтобы целы были или чтобы программа делала то что надо?

loz ★★★★★
()
Ответ на: комментарий от loz

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

linearisation
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.