Нарушение принципа подстановки Лискова - PullRequest
1 голос
/ 10 апреля 2019

У меня есть следующий код

public class A 
{
      public double foo(double y) 
      {
             return real_value;
      }
}

, где вход для метода foo -1 < y < 1 и результат функции - действительное число, большее нуля.

ТогдаУ меня есть унаследованный class B, который наследует class A и переопределяет метод foo.

public class B extends A 
{
      public override double foo(double y)
      {
         return real_value;
      }
}

, где вход для метода foo 0 < y < 1 и результат функции любойдействительное число.

Нарушается ли здесь принцип подстановки Лискова?

заранее спасибо.

Ответы [ 2 ]

1 голос
/ 16 апреля 2019

Предполагая, что вы хотите использовать B в качестве подтипа A в вашей программе:
Да, ваш код явно нарушает LSK.

Почему?
Аргументы должны быть контравариантными.

Что это значит?
Принцип Лискова гарантирует, что ваша программа будет работать без изменений, если ваш подтип B будет заменен базовым типом A.

Или, точнее (Барбара Лисков, 1987):

«Если для каждого объекта o1 типа B существует объект o2 типа A
такой, что для всех программ P, определенных в терминах A, поведение P остается неизменным
когда o1 заменяет o2, тогда B является подтипом A ”.

Например:

   class Duck               { void fly(int   height) {} }
   class RedheadDuck : Duck { void fly(long  height) {} }
   class RubberDuck : Duck  { void fly(short height) {} }

   class LSPDemo
   {
      public void Main()
      {
         Duck p;

         p = new Duck();
         p.fly(int.MaxValue); // Expected behaviour

         p = new RedheadDuck();
         p.fly(int.MaxValue); // OK   

         p = new RubberDuck();
         p.fly(int.MaxValue); // Fail 
      }
   }

=> the program behaves unchanged, if the argument is contravariant.
=> e.g. base type <= sub type
=> RubberDuck violates this principle, as it does not allow all values of the base type Duck

В вашем коде тип базового класса A foo будет ожидать значения аргумента -1 Ваш подкласс B foo будет ожидать значения аргумента 0 Если ваша программа заменит подкласс базовым классом, ваша программа не будет работать так, как ожидается для foo в отношении значений <= 0. </p>

EDIT : Несмотря на то, что вы используете тип double для аргументов обоих методов foo, я предполагаю, что вы защищаете свои методы, проверяя значения и их область видимости. Это приведет к описанному сбою, аналогичному примеру.

P.S .: Да, это зависит от контракта, который вы определяете для foo. Предполагая, что вы хотите использовать B как подтип A, это нарушает LSK. В противном случае это просто метод переопределения.

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

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

...