【问题标题】:Understanding Liskov Substituion Principle [duplicate]了解 Liskov 替换原则
【发布时间】:2016-08-20 15:32:36
【问题描述】:

我的示例程序如下所示;

    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();
        }

据我了解,当我们为 obj3 之类的 Animal 创建 Dog 实例时,我们违反了 LSP。请确认我的理解。如果是,请告诉我在这种情况下如何实现以更好地理解。我认为我的编码在概念上是正确的

【问题讨论】:

  • 你为什么认为这会破坏 LSP? (它没有...)
  • 您希望它在编译时失败还是希望得到不同的输出?

标签: c# design-patterns liskov-substitution-principle


【解决方案1】:

你没有违反 Liskov 替换规则。

简单英语中的 Liskov 替换规则 -> 如果 Base.Method 留下任何不变量,则 Derived.Method 必须保留这些不变量。

invariant 是对象的状态,不会因为方法执行而改变。

例如:

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 中,因此没有破坏 Liskov 替换规则。

【讨论】:

  • 好的,所以我又添加了一个名为 woodDog 的类,它是由木头制成的玩具狗。所以他发不出声音。在这里,如果我创建从 Animal 继承的 WoodDog 类,我就违反了 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 是-a Bird,它有Fly(height=10) 的方法,所以我可以在技术上做类似的事情,

Bird b = new Penguin();
b.Fly(height=100);
b.Swim(depth=20);

这违反了企鹅的能力(他不能飞那么高,他只能飞到0,也许......?)。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2010-12-03
  • 2015-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-13
  • 2014-06-05
相关资源
最近更新 更多