Нужна ясность в Понимании принципа замещения лисков - PullRequest
0 голосов
/ 02 апреля 2019

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

  1. Предусловия не могут быть усилены в подтипе
  2. Постусловия не могут быть ослаблены в подтипе.
  3. Инварианты супертипа должны сохраняться в подтипе.

ДляНапример, у меня есть классы ниже Это нарушение (Предварительные условия не могут быть усилены в подтипе).Я пытаюсь обернуть голову вокруг этого, Может кто-нибудь дать хороший пример, чтобы понять это.

Class Switch:
   def __init__(self,ip,dc):
       self.ip=ip
       self.dc=dc

class CiscoSwitch(Switch):
   def __init__(self,ip,dc,zone):
       super().__init__(ip,dc)
       self.zone=zone

class JuniperSwitch(Switch):
   def __init__(self,ip,dc,zone):
       super().__init__(ip,dc)
       self.zone=zone

1 Ответ

0 голосов
/ 02 апреля 2019

Принцип LSP работает через интерфейсы, то есть то, что является общедоступным в объекте / значении. В случае с Python у вас есть общедоступные атрибуты и методы, и поэтому, если вы реализуете интерфейс, вы должны его придерживаться. В вашем примере класс Switch определяет интерфейс только относительно его атрибутов, то есть он имеет поля ip и dc. Поскольку вы вызываете super в CiscoSwitch и JuniperSwitch, они оба имеют эти поля и поэтому реализуют «интерфейс» Switch и могут заменить его.

Теперь давайте рассмотрим условия, которые вы упомянули:

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

Предположим, у вас есть интерфейс с методом, который окрашивает фигуру, и этот метод принимает только шестнадцатеричные цвета ("#123456") или цвета rgb ((123,124,125)). Предположим, вы создали класс Rectangle, который реализует этот интерфейс, но принимает только цвета rgb. Вы усиливаете предварительное условие. Если у вас есть эта строка в вашем коде: generic_shape.color("#123456")

Вы не можете заменить свой прямоугольник в нем, поэтому вы нарушаете LSP.

  1. Постусловия не могут быть ослаблены в подтипе

Классическим примером будет возвращение None для метода, который не должен возвращать None. Предположим, что в интерфейсе Shape у вас есть метод getSide, и вы создаете класс Circle, а при реализации этого метода вы возвращаете None. Это нарушает ожидания вызывающего абонента и может вызвать неожиданную ошибку:

side = generic_shape.get_side() # suppose it is a circle
scaled_side = side * 2 # you get an error
  1. Инварианты супертипа должны быть сохранены в подтипе

Этот, на мой взгляд, более сложный, потому что его трудно сделать явным. Единственный пример, который я могу себе представить, это сохранение свойства не равным Null, предположим, что в вашем примере у вас есть Switch, который не использует IP (возможно, использует MAC-addr), если интерфейс Switch ожидает, что поле ip не должно быть Нет, ваш MAC-Switch будет работать с этим интерфейсом.

Надеюсь, это поможет!

...