LINUX.ORG.RU

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

 ,


0

3

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

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

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

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

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

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

Ответ на: комментарий от den73

Из этого определение не следует нерелевантность ни одного из моих примеров

Твои примеры (бессмысленные) не проходят проверку принципом Лисков. Всего лишь.

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

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

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

Это твое право, естественно - принцип Лисков не является строго доказанной теоремой.

Он вообще теоремой не является. Теорема или гипотеза могла бы быть сформулирована в какой-то такой вот форме: «соблюдать принцип лисков при проектировании лучше(по таким то и таким то критериям), чем не соблюдать». А тут всего лишь декларация, которая вобще ни на чем не основывается, просто кому то так нравится. Ванечке нравится ковыряться в носу, поэтому должен соблюдаться принцип Ванечки — вот в таком духе. Собрались 2 аута в треде, и трут непонятно о чем.

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

Вот именно «подстановка тела» и делает определение q(x) бесполезным.

На самом деле первоисточник вот Я неоднозначно написал, исправляюсь. В Яре нет ООП, но я напишу, как будто оно есть:

о.класс Родитель ()
  метод М() -- целое виртуальный да
кнк
  
о.класс Ребёнок (Родитель)
  метод М() -- целое перекрытый-виртуальный да
кнк

о.метод Родитель.М() -- целое виртуальный да
  возврат 0
кнм

о.метод Ребёнок.М() -- целое перекрытый-виртуальный да
  возврат 1
кнм

выполнить-при-загрузке
  пусть Экземпляр = н.Родитель; // или н.Ребёнок
  пусть q -- да-нет = (: Экземпляр.М() == 0 :)
  печать q
кнв
Свойство q(x) - «метод М объекта x возвращает 0». Я даже не буду тебя спрашивать, релевантно ли это, я процитирую первоисточник, стр. 16:

First, properties of an object's behavior in a particular program must be preserved: to ensure that a program continues to work as expected, calls of methods made in the program that assume the object belongs to a supertype must have the same behavior when the object actually belongs to a subtype.

Теорию про инварианты и констрейнты я не читал, но в статье рассмотрено три примера «правильного» создания подтипа:

1. Добавление методов без добавления состояния

2. Сужение типа, т.е. вместо стека рассматривается стек глубиной 20.

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

Т.е., типичная ситуация, когда Widget превращается в WidgetWithFrame путём наследования, скорее всего, не соответствует принципу Лисков.

Я теперь уже не так уверен, потому что понял, что в Википедии принцип сформулирован вне соответствия с первоисточником. В первоисточнике понятие о q сужено. Но это не значит, что ты (автор класса) можешь выбирать q. Множество возможных q автоматически следует из выбранного языка программирования и определения базового класса.

И так скажем, на 95% я уверен, что принцип Лисков не соответствует практике применения ООП.

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 5)
Ответ на: комментарий от den73

типичная ситуация, когда Widget превращается в WidgetWithFrame путём наследования, скорее всего, не соответствует принципу Лисков.

Еще один последний раз: принцип Лисков предназначен для оценки используемых контрактов, а не для оценки формы графа наследования.

Но это не значит, что ты (автор класса) можешь выбирать q. Множество возможных q автоматически следует из выбранного языка программирования и определения базового класса.

Если определение базового класса делаю не я - естественно, его контракт задаю не я. Мой производный класс должен всего лишь выполнить этот контракт.

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

Еще один последний раз: принцип Лисков предназначен для оценки используемых контрактов, а не для оценки формы графа наследования.

Речь не о форме, а о вирт.ф-ях. Виртуальные ф-ии, определённые в базовом классе и перекрытые в наследниках, скорее всего, нарушают принцип Лисков. Собственно, о том и пример про прямоугольник и квадрат. На практике желание пронаследовать квадрат от прямоугольника вполне объяснимо, а оказывается, принцип Лисков при этом нарушается. Думаю, навязывание этого принципа является формой конкурентной борьбы: нужно задать такие правила использования инструментов, чтобы в реальности их использовать было невозможно. Как написано в книжке «Анастасия», жрецы долго думали, как ускорить свою мысль, но у них ничего не вышло. Тогда они решили замедлить мысль всех остальных людей и получить преимущество хотя бы так.

Но я не понял: тебе это всё равно, ты с этим несогласен или что.

Например, QWidget имеет метод QWidget::heightForWidth(int w), который переопределён в его потомках. Значит, Qt не соблюдает принцип Лисков.

den73 ★★★★★
()

дело в том что setWidth и setHeight существуют. А квадрат на них не реагирует. прямоугольник среагировал бы правильно, а квадрат - нет. это и есть нарушение принципа.

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

Еще один последний раз: принцип Лисков предназначен для оценки используемых контрактов, а не для оценки формы графа наследования.

Речь не о форме, а о вирт.ф-ях.

Речь о вирт.ф-ях ведешь только ты. Принцип Лисков говорит о контрактах классов в иерархии.

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

facepalm.jpg

Но я не понял: тебе это всё равно, ты с этим несогласен или что.

С чем «этим» - с книжкой «Анастасия»? Я не знаком с ней и не собираюсь знакомиться. Или с твоим пониманием принципа Лисков? Ты вообще говоришь о чем-то, что к нему не относится.

Например, QWidget имеет метод QWidget::heightForWidth(int w), который переопределён в его потомках. Значит, Qt не соблюдает принцип Лисков.

Возможно. Расскажи, какой контракт здесь нарушается.

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

Возможно. Расскажи, какой контракт здесь нарушается.

Вопрос упирается в вопрос «каков контракт QWidget». Если мы считаем контрактом документацию, то ничего, кроме сигнатуры и виртуальности, не определено. Если мы говорим о поведении программ, то реальное поведение у QWidget есть, программу, которая его использует, составить можно и принцип будет нарушен.

Здесь выясняется ещё один нюанс, что в оригинале говорится о _доказуемых_ свойствах, а в википедии - о _верных_ свойствах. Вывод отсюда таков, что не надо читать википедию, конечно же. Если свойства доказуемы, то можно говорить о «контракте» (о документации плюс интерфейсе) и о реализации (о поведении реальных программ). И при изучении программ можно говорить о разной аксиоматике: либо мы доказываем на основе документации, либо на основе реализации.

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

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

Расскажи, какой контракт здесь нарушается.

Вопрос упирается в вопрос «каков контракт QWidget»

Ты так уверенно говорил о нарушении, что я было подумал - ты знаешь этот контракт.

Если мы считаем контрактом документацию, то ничего, кроме сигнатуры и виртуальности, не определено.

Итак, этот контракт не нарушен...

Если мы говорим о поведении программ, то реальное поведение у QWidget есть, программу, которая его использует, составить можно и принцип будет нарушен.

...но ты можешь придумать такой контракт, который невозможно не нарушить. Окей. Ты из этого пришел к ненужности принципа Лисков?

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

Нет. Если контракт - это тест, а тест успешно выполняется и на QWidget, и на его потомке, то контракт не нарушен.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

ты знаешь этот контракт.

Его нельзя «знать». Это вопрос соглашения, я тебе предложил два варианта. А ты вместо того, чтобы начать разговор о том, что считать контрактом, пытаешься вывести меня на признание ошибки.

Да, если тебе это надо - я ошибся в том, что поверил Википедии. Её не надо было читать. И я говорил не о ненужности, а о парадоксальности (некорректности), которая есть в Википедии, но которой нет в первоисточнике. Конечно, парадоксальный принцип не нужен.

Ладно, он не парадоксален. Вопрос нужности остаётся. С одной стороны, вроде всё круто.

Но у меня получается, что если виртуальная функция является частью контракта, то она должна быть в базовом классе абстрактной (и на самом деле быть исключена из контракта) и по любой цепочке наследования должна переопределяться не более одного раза. Здесь получается иной парадокс: «опа есть, а слова нет». Т.е. мы заводим виртуальную функцию (скажем, draw) для полиморфизма, но контракта нет и пользоваться в базовом классе, не нарушив принцип Лисков, ей как бы нельзя. Но в реальности, именно этой вирт.ф-ей и надо пользоваться, и именно для базового класса всех виджетов, чтобы фактически нарисовать какой-нибудь грид виджетов.

В Qt я полез в примера подобной конструкции, но за 10 минут ничего лучше, чем QWidget::heightForWidth не нашёл. Думаю, принцип Лисков всё же тут нарушается, потому что нужно было бы написать «не вызывайте heightForWidght для QWidget». И естественно, компилятор бы не мог это проверить, что противоречит практичности.

Данного примера недостаточно, чтобы понять, применяется ли в Qt принцип Лисков. Мне всегда казалось, что в библиотеке виджетов есть базовый виртуальный Draw, который ничего не делает, и он несколько раз перегружается по иерархии. Т.е. никаким принципом Лисков и не пахнет. Как раз наоборот, виртуальность используется для того, чтобы рисовать разные виджеты по-разному, не зная конкретного типа виджета. Конечно, можно организовать это и по-другому. Но что-то мне сдаётся, что очень часто конкретный виджет рисуется не так, как его предок, который зачастую тоже может рисоваться.

Ладно, спасибо за беседу. Нужно будет потом ещё помедитировать над этим принципом. Он хорош тем, что определяет вменяемое понятие «подтипа» и в принципе позволяет частично обобщить понятие «подтипа» с базовых типов на объекты. Но вообще говоря, наследник в смысле ООП не является подтипом. И для разработки языка остаётся вопрос, как работать с «наследником в смысле ООП», как его назвать и нужно ли вообще такое понятие, как «наследник в смысле ООП».

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 2)
Ответ на: комментарий от den73

Данного примера недостаточно, чтобы понять, применяется ли в Qt принцип Лисков

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

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

Ну и зачем ты это написал? Понятно же, что мы не видим процесса проектирования Qt, а видим только результат, значит, понятно из контекста, о чём я говорю. С целью придраться к словам? Хорошо, пусть будет «соблюдается в Qt». Похоже, что «не соблюдается». И возникает вопрос: в каких практически значимых программах на любом языке он действительно соблюдается?

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 4)
Ответ на: комментарий от den73

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

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от AndreyKl

Это заблуждение. В принципе лисков явно указано, что реакция должна быть *правильной* для объекта, а не правильной *вообще*(чего по сути не существует). Иными словами, подкласс должен поддерживать тот же протокол сто и класс, не более того. Что является правильным поведением для конкретного экземпляра — есть предмет соглашений.

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

Я думаю, что разумнее сделать наоборот: прямоугольник подклассом квадрата, т. к. у прямоугольника есть доп. методы. Тогда любой прямоугольник может наследовать методы квадрата set_side, resize, move, draw, clear и т. д. и определять 2 дополнительных: set_width и set_height. И никаких противоречий не будет.

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

В общем, мой окончательный вывод:

Принцип Лисков разумен и имеет смысл. Но он имеет мало отношения к практике ООП. Лисков проанализировала то, что легко подогнать под теорию (типичное поведение теоретика). Есть анекдот про математиков на воздушном шаре. Нормальная практика ООП (метод draw) не подходит под принцип Лисков. Но это значит не то, что данная практика порочна, а то, что теория недостаточно развита. Соответственно, применять этот принцип в практике программирования, вообще говоря, не нужно. Если есть ясное понимание, как этот принцип полезен в конкретном проекте - можно им руководствоваться. Но общие слова о «хорошей архитектуре» не могут быть обоснованием.

С точки зрения языка, наследование в ООП иногда действительно создаёт подтипы и неплохо бы, чтобы компилятор это понимал. Но, как правило, оно создаёт новые типы, не являющиеся подтипами родителя. В частности, любая иерархия виджетов с виртуальным draw не соблюдают принцип Лисков.

Но проблема тем не менее есть: наследники обычно не являются подтипами своих предков.

Вот это

>(defclass Родитель () ())
#<STANDARD-CLASS COMMON-LISP-USER::Родитель>
>(defclass Ребёнок (Родитель) ())
#<STANDARD-CLASS COMMON-LISP-USER::Ребёнок>
>(subtypep 'Ребёнок 'Родитель)
T
T
можно расценивать как ошибку дизайна Common Lisp, если мы принимаем принцип Лисков для подтипов. Для выражения наследования нужно _ещё_одно_ отношение, не subtype.

Этим путём я и собираюсь следовать, если в Яре будет ООП в собственном смысле слова.

Критика приветствуется.

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

И так скажем, на 95% я уверен, что принцип Лисков не соответствует практике применения ООП.

Именно потому он и был сформулирован. Чтобы начали писать программы, в соответствии с ним, а не абы как.

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

Но это значит не то, что данная практика порочна

В данном случае - именно это и значит. Нарушение принципа Лисков - первый звоночек на тему «вы готовите ООП не правильно!».

В частности, любая иерархия виджетов с виртуальным draw не соблюдают принцип Лисков.

соблюдает, конечно. С чего бы нет?

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

SOLID или принцип Лисков? В любом случае, хотелось бы увидеть линк.

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

Нарушение принципа Лисков - первый звоночек на тему «вы готовите ООП не правильно!».

Это лишь чьё-то мнение.

соблюдает, конечно. С чего бы нет?

С того бы.

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

Уточнение: это верно в том случае, если существует вызов widget.draw, к-рый в реальности вызывает childWidget.draw и, таким образом, draw де-факто входит в контракт widget (независимо от того, что написано в проекте, есть де-факто используемый интерфейс widget).

Также это верно, если по какой-то цепочке наследования draw перекрыт более чем один раз.

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

Также это верно, если по какой-то цепочке наследования draw перекрыт более чем один раз.

это какая то необычная интерпритация принципа лисков. принцип в сущности то прост. на примере квадрата как подтипа прямоугольника всё просто:

У нас есть метод checkInvariants который принимает прямоугольник

void checkInvariants(Pramougolnik pr) {
  pr.setWidth(15)
  pr.setHeight(20)
  return pr.getWidth() == 15 && pr.getHeight() == 20
}


затем, в этот метод передаётся либо квадрат либо прямоугольник.

так вот для любого прямоугольника метод будет возвращать истину. а для квадрата ложь. Именно это и имеется ввиду когда говорят о принципе лисков. классы ведут себя по разному, инварианты нарушаются. То что вы с анонимусом можете задавать инварианты как угодно ежу впринципе понятно. Но вот чего вы никак не поймёте, так это то что _ожидаемое_ поведение для обычного класса в обычной ситуации - это посавить видтх в 15 и получить обратно 15. то же и с высотой. И нормальный программист будет ожидать нормального поведения когда будет работать с классом. а оно чёртас два нормальное. установил ширину в 15, потом никого не трогая установил высоту, а высота поменялась. А у прямоугольника не менялась. Вот в этом то и нарушение принципа. Вы с анонимусом задрали безграмотностью. книжек что ли почитайте вумных.

АПД. ну и да, это лишь пример

AndreyKl ★★★★★
()
Последнее исправление: AndreyKl (всего исправлений: 1)
Ответ на: комментарий от AndreyKl

У принципа Лисков, кроме примеров, есть ещё и определение. Я про квадрат с прямоугольником вообще особо не говорил в этой теме.

Давай так: есть виджет «окружность», у него перекрыт виртуальный метод draw, так что он рисует, естественно, окружность.

Вопрос N1 - является ли частью «контракта» виджета «окружность» то, что он рисует окружность? Дурацкий вопрос, правда? Конечно, да, иначе зачем он ещё нужен?

Далее мы наследуем от виджета окружность и делаем виджет «круг», т.е. «окружность, заполненная внутри» - переопределяем виртуальный метод draw.

Далее мы пишем программу, рисующую окружность. Далее в ней заменяем виджет «окружность» виджетом «круг». И - вуаля! Мы по определению нарушили принцип Лисков, потому что поведение программы не должно было измениться от замены класса на подкласс (см. формулировку принципа Лисков).

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

В чём проблема с моим рассуждением?

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 2)
Ответ на: комментарий от den73

В частности, любая иерархия виджетов с виртуальным draw не соблюдают принцип Лисков.

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

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

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

Ты неправ, я всё понял. На самом деле не в отрыве от контракта - контракт един, он либо нарушается, либо нет. В принципе Лисков ничего не говорится о дроблении контракта на какие-то отдельные части. Ты можешь просто сказать своё мнение на тему, является ли draw частью контракта widget?

а) является

б) не является

в) как договоримся

г) иное

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 3)
Ответ на: комментарий от den73

P.S. насколько я понимаю, ты предлагаешь абстрагироваться от конкретной сигнатуры класса и рассматривать контракт абстрактно. Это выглядит довольно неуклюжей уловкой, но пусть даже так.

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

Далее мы пишем программу, рисующую окружность. Далее в ней заменяем виджет «окружность» виджетом «круг». И - вуаля! Мы по определению нарушили принцип Лисков, потому что поведение программы не должно было измениться от замены класса на подкласс (см. формулировку принципа Лисков).

По-моему бредовенько. Это ты сам выдумал или в книжке какой прочитал?

И да, на мой взгляд, конкретно в этом случае проблема с твоим рассуждением в том что метод draw обещает нам отрисовать объект так как положено отрисовывать объект. И именно это и будет ожидать любой нормальный человек. И это и есть контракт draw - отрисовать правильно объект. Так что ничего тут не нарушается.

AndreyKl ★★★★★
()
Последнее исправление: AndreyKl (всего исправлений: 2)
Ответ на: комментарий от den73

в) как договоримся

Это.

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

Ты понимаешь неправильно и всё больше впадаешь в откровенный бред.

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

По-моему бредовенько.

Прекрасно, но это математика и это не аргумент.

И это и есть контракт draw - отрисовать правильно объект.

Не хватает только метода «сделать, чтобы было хорошо». Извини, но это не контракт. Контракт должен говорить, как конкретно прорисовать объект, а не «правильно».

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

Прекрасно, но это математика и это не аргумент.

слушай, ну ты нормальный?

вот есть виджет. у него есть дроу. что делает дроу у виджета? отрисовывает виджет, понимаешь?

дальше, окружность, наследник виджета. что делает дроу у окружности? отрисовывает виджет, который в данном случае окружность.

дальше, круг, наследник окружности, виджета. что делает дроу у круга? отрисовывает виджет, который в данном случае, сюрприз-сюрприз... КРУГ!!!!

ну и где нарушение?

хочешь, вырази на языке математики. всё там сойдётся, не волнуйся.

Не хватает только метода «сделать, чтобы было хорошо». Извини, но это не контракт. Контракт должен говорить, как конкретно прорисовать объект, а не «правильно».

и как же интересно задать контракт в таком случае для абстрактного объекта виджет?

AndreyKl ★★★★★
()
Последнее исправление: AndreyKl (всего исправлений: 1)
Ответ на: комментарий от tailgunner

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

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

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

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

Ну вот, и ты туда же: т.е. неважно, что он отрисовывает, главное, чтобы что-то отрисовывал. А по принципу Лисков, если это важно, то все потомки должны отрисовывать то же самое, что и предок. Смотришь в википедию и подставляешь:

T - виджет окружность

S - виджет круг

q(x) - виджет рисует окружность

Обрати внимание, что q(x) ты не можешь выбирать, q(x) - это _произвольное_ доказуемое свойство, вытекающее из контракта класса.

Т.е. у тебя остаётся лишь один вариант: объявить вслед за Tailgunner, что неважно, что рисует виджет.

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

Как только ты спохватишься и скажешь, что виджет окружность должен рисовать окружность, сразу окажется, что «рисовать окружность» является доказуемым (из контракта) свойством виджета окружность, и тогда виджет круг тоже должен рисовать окружность (подставь ещё раз в принцип Лисков). Пойми ещё раз: ты не имеешь права выбирать q(x), q(x) - это _любое_ свойство, вытекающее из контракта. Как там, для любого эпсилон существует дельта и так далее. Не тебе выбирать эпсилон.

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

Хорошо, что я от этого всегда умел уклоняться, авось и дальше пронесёт.

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

и как же интересно задать контракт в таком случае для абстрактного объекта виджет?

В случае абстрактного объекта в принципе можно отмазаться, сказав, что метод Draw есть, но он ничего никому не должен. Я недаром привёл именно такой пример, какой привёл - два конкретных объекта, наследующих друг от друга.

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

почему q(x) рисует окружность то?

в этом и момент, ты задаёшь контракт который выглядит странно. q(x) рисует виджет. и всё ок.

не вытекает из контракта что q(x) рисует окружность. чего оно у тебя вытекает? потому что контракт ты так составил. так в таком случае его что угодно нарушит. составь правильно и всё будет ок.

AndreyKl ★★★★★
()
Последнее исправление: AndreyKl (всего исправлений: 2)
Ответ на: комментарий от den73

что с людьми определённых убеждений я вряд ли смог бы работать

ну за живое задел. что не так с убеждениями?

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

т.е. вот гляди. если q(x) трактовать так как ты, то выходит что вообще наследовать нельзя. т.е. в итоге то мы наследуем для того чтобы изменить поведение. Т.е. наследующий класс будет обладать некоторыми другими доказуемыми свойствами чем наследуемый. Причём можно смело утверждать что это _всегда_ так (ну или приведи контрпример).

и если брать твою трактовку то наследование само по себе нарушает прицип лисков. но согласись это бредовенько.

AndreyKl ★★★★★
()
Последнее исправление: AndreyKl (всего исправлений: 1)
Ответ на: комментарий от den73

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

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

то выходит что вообще наследовать нельзя. т.е. в итоге то мы наследуем для того чтобы изменить поведение.

Поздравляю - ты нарушаешь принцип Лисков.

и если брать твою трактовку то наследование само по себе нарушает прицип лисков. но согласись это бредовенько.

Нет, есть варианты наследования, которые его не нарушают. Но их очень мало. См. примеры в статье.

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от den73

Поздравляю - ты нарушаешь принцип Лисков.
Нет, есть варианты наследования, которые его не нарушают. См. примеры в статье.

ох ты блин, ладно. пойду прочитаю. потом если что посыплю голову пеплом.

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

Вот тебе практически прямая цитата про круг и окружность:

to ensure that a program continues to work as expected, calls of methods made in the program that assume the object belongs to a supertype must have the same behavior when the object actually belongs to a subtype.

Ссылку уже давал на первой странице. Повторяю. http://reports-archive.adm.cs.cmu.edu/anon/1999/CMU-CS-99-156.pdf

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

ты знаешь, читал статью в английской вики, и во первых строках вот что прочёл

if S is a subtype of T, then objects of type T may be replaced with objects of type S (i.e. an object of type T may be substituted with any object of a subtype S) without altering any of the desirable properties of T (correctness, task performed, etc.)

таки заметь *desirable* properties of T. так что шах и мат (если вики не врёт конечно).

AndreyKl ★★★★★
()
Последнее исправление: AndreyKl (всего исправлений: 1)
Ответ на: комментарий от den73

в том смысле что нужные свойства всё таки выбираем мы. что в общем-то весьма логично. строим программу, выбираем свойства.

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

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

to ensure that a program continues to work as expected, calls of methods made in the program that assume the object belongs to a supertype must have the same behavior when the object actually belongs to a subtype.

однако ты трактуешь очень широко. просто выбери _нужные_ _тебе_ свойства, и строй для них иерархию, и у тебя будет соблюдаться принцип.

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

AndreyKl ★★★★★
()
Последнее исправление: AndreyKl (всего исправлений: 1)
Ответ на: комментарий от den73

Ну и да, убеждения это концентрированное знание. В моём случае. А если у тебя убеждения, а основания у них хлипкие, так конечно, нафиг такие убеждения.

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