Это не является очевидным или типичным нарушением LSP, и можно утверждать, что это вообще не нарушение LSP, но вот моя интерпретация:
Ожидается, что Shape
описывается своим полем type
. Когда DrawShape
получает объект Shape
, может произойти одно из нескольких. В зависимости от значения поля type
он может попытаться привести объект к Square
и вызвать его функцию Draw
, или попытаться привести его к Circle
к тому же концу. Тем не менее, это не гарантированно работает как ожидалось для произвольного Shape
. В частности, он будет работать только в том случае, если динамический тип объекта фактически соответствует семантическому значению его поля type
. Если поле type
не соответствует его динамическому типу, при попытке выполнить динамическое приведение произойдет исключение. Это поведение DrawShape
данного Shape
объекта.
Однако, учитывая Square
или Circle
, ожидалось другое. В частности, ожидается, что функция всегда будет выполнять тот или иной путь без исключения, поскольку семантическая импликация поля type
всегда будет соответствовать динамическому типу объекта.
Другими словами, можно считать, что функция DrawShape
имеет четыре интересных пути выполнения для объекта Shape
: исключение, возникающее при динамическом приведении Circle
, исключение, возникающее при динамическом приведении Square
или успешное выполнение функций рисования Square
или Circle
.
Когда замещается дочерний элемент, первые два упомянутых пути больше не возможны, и для данного дочернего элемента возможен только один путь.
В качестве альтернативы можно утверждать, что нарушения LSP нет; функция по-прежнему «действует» для дочерней замены так же, как и для родительской. Squares
и Circles
просто имеют дополнительное значение, так как поле type
будет точно соответствовать динамическому типу объекта, ограничивая результаты выполнения функции во время выполнения. Хотя это можно рассматривать как изменение ожиданий функции, его также можно рассматривать как навязывание предварительного условия.
Редактировать
Полагаю, я забыл ответить на часть вопроса: причина, по которой это предполагаемое нарушение LSP "вызывает" нарушение OCP, заключается в том, что логика функции, вызывающая различное поведение для Shapes
и Squares
и Circles
будучи динамическим приведением к дочерним элементам, это та же логика, которая заставляет класс Shape
зависеть от его дочерних элементов. Таким образом, нарушая LSP с помощью условной логики для подклассов, он, в свою очередь, нарушает OCP.
Я не знаю, действительно ли я сам назвал бы этот конкретный случай ситуацией "причинности", а не просто пересечением событий, но, возможно, это было намерение автора.