LINUX.ORG.RU

Вопрос по принципу подстановки Лисков

 ,


0

2

Подскажите пожалуйста, а правильно ли я понимаю, что данный принцип можно свести к следующему: мы имеем право сужать определение типа в подтипе(сужать — в смысле, добавлять определения — специализировать) но не изменять?

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

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

keinu
()

но не изменять?

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

anonymous
()

Нет такого принципа. Формальное определение бессмысленно, неформальных трактовок масса.

Единственное применение — собеседование, когда тебя про SOLID спросят. Тут просто зазубри пару абзацев из википедии, и всех делов.

Единственное осмысленное предложение, хотя бы отдаленно относящееся к этому принципу: если метод возвращает строку «Hello, world!», то наследнику лучше не кидать исключение, которое полностью поломает всю программу, когда этого никто не ждет. Лучше строчку и вернуть, «Not implemented yet», например.

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

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

То что я сказал в стартовом топике, де-факто гарантирует это

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

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

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

оно запрещает изменение реализации,

разве Вы, изменив реализацию (в подтипе) сможете гарантировать, то что Вы процитировали?

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

например,

myType foo --> 1; myType foo == 1 --> true
mysubType foo --> somethingElse; myType foo == 1 --> false

это прямое следствие изменения реализации.

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

это прямое следствие изменения реализации.

Это зависит от спецификации. Если в ней сказано, что foo должно быть единицей и только ей - то нарушает. Если же не сказано - не нарушает.

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

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

В Вашем примере интересно утверждение, которое было сделано относительно типа. Вероятно, оно должно было выглядеть как-то так: «для любого объекта класса MyType метод foo всегда возвращает значение 1».

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

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

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