Понимание принципа подстановки Лискова
Мой пример программы, как показано ниже;
public class Animal
{
public virtual string MakeSound()
{
return "General Sound";
}
}
public class Dog : Animal
{
public override string MakeSound()
{
return "Bow..Bow..";
}
}
}
static void Main(string[] args)
{
Animal obj1 = new Animal();
Console.WriteLine("General Animal's sound id " + obj1.MakeSound());
Dog obj2 = new Dog();
Console.WriteLine("Dog Animal's sound id " + obj2.MakeSound());
//Violate LSP
Animal obj3 = new Dog();
Console.WriteLine("Animal's sound id " + obj3.MakeSound());
Console.ReadKey();
}
Здесь, насколько я понимаю, когда мы создаем экземпляр Dog для Animal, такой как obj3, мы нарушаем LSP. Пожалуйста, подтвердите мое понимание. Если да, скажите, пожалуйста, как добиться в этом случае лучшего понимания. Я думаю, что мое кодирование является концептуально правильным
2 ответа
Ваш пример на самом деле не нарушает LSP. Я думаю, что лучшим примером нарушения будет что-то вроде
public class Bird
{
public virtual void Fly(int height);
}
public class Penguin : Bird
{
public virtual void Swim(int depth);
}
public static class BirdExtensions
{
public static void Fly(this Bird bird)
{
}
}
Если я передам экземпляр Penguin этому методу, мне, возможно, придется сгенерировать исключение во время выполнения или что-то еще, потому что мой Penguin не может летать:(
Вы видите, что мы сделали предположение о базовом классе (все птицы могут летать), но теперь у нас есть пример дочернего класса, который не соответствует этому предположению (пингвины не могут летать).
Кроме того, потому что Penguin
это Bird
, у него есть метод для Fly(height=10)
так что я мог бы технически сделать что-то вроде,
Bird b = new Penguin();
b.Fly(height=100);
b.Swim(depth=20);
Что нарушает возможности Пингвина (он не может летать так высоко, он может летать только в 0, может быть...?).
Вы не нарушаете правила замещения Лискова.
Правило замены Лискова на простом английском -> если Base.Method
оставляет какие-то инварианты, то Derived.Method
должны поддерживать эти инварианты.
инвариант - это состояние объекта, которое не изменяется в результате выполнения метода.
например:
public class MyInt{
private int num1 = 5;
public void print(){
Console.write(num1);
}
public void increment(){
num1++;
}
}
здесь инварианты print
только num1
потому что это не изменилось. инварианты increment
не, потому что это меняет все MyInt
члены.
В вашем примере:
инвариант, который Animal.MakeSound
имеет: не
инвариант, который Dog.MakeSound
имеет: не
инварианты Animal.MakeSound
поддерживаются в Dog.MakeSound
Таким образом, правило подмены Лискова не нарушено.