Lan*_*eyo 4 c# liskov-substitution-principle code-contracts solid-principles
我刚刚安装了Microsoft Code Contracts.它是.NET Framework和Visual Studio插件的一部分.它提供运行时检查和定义合同的静态检查.
该工具有四个警告级别,所以我设置最高.
我已经宣布了违反Liskov替代原则的课程.
public class Person
{
protected int Age { get; set; }
public Person(int age)
{
Contract.Requires(age > 0);
Contract.Requires(age < 130);
this.Age = age;
}
}
public class Child : Person
{
public Child(int age) : base(age)
{
Contract.Requires(age > 0);
Contract.Requires(age < Consts.AgeOfMajority);
Contract.Requires(age < 130);
this.Age = age;
}
}
public static class Consts
{
public readonly static int AgeOfMajority = 18;
}
Run Code Online (Sandbox Code Playgroud)
LSP声明:
如果S是T的子类型,那么类型T的对象可以用类型S的对象替换而不改变该程序的任何所需属性
在我的例子中,违规将是这个对齐:Person person = new Child(23);.我们应该能够做到这一点,但我们不能因为孩子不能比某个年龄小于人类所要求的年龄.
然而,分析结果令人惊讶CodeContracts: Checked 11 assertions: 11 correct.我的示例是错误的还是Code Contracts没有检测到这样的事情?
wes*_*ton 15
虽然LSP确定子类型不能在方法上放置更多限制性前置条件,但这不适用于构造函数,因为您不以多态方式使用构造函数.
合同违规将new Child(23);在分配给a之前发生Person.
因此,示例违规是错误的,它不会创建子类型S的实例,更不用说为T替换它.
有一个着名的LSP违规示例:
但是,我们不能在构造函数中违反它.假设我们有Duck和WildDuck类:
public abstract class Duck
{
public abstract string Quack();
public double Weight { get; set; }
public Duck(double weight)
{
Contract.Requires(weight > 0);
this.Weight = weight;
}
}
public class WildDuck : Duck
{
public WildDuck(double weight)
: base(weight)
{
Contract.Requires(weight > 0);
this.Weight = weight;
}
public override string Quack()
{
return "wild quack";
}
}
Run Code Online (Sandbox Code Playgroud)
现在让我们介绍一下ElectricDuck:
public class ElectricDuck : Duck
{
public Battery Battery { get; set; }
public override string Quack()
{
return "electric quack";
}
public ElectricDuck(double weight, Battery battery)
: base(weight)
{
Contract.Requires(weight > 0);
Contract.Requires(battery != null);
this.Weight = weight;
this.Battery = battery;
}
}
public class Battery
{
public bool IsEmpty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在第一眼看来它似乎违反了LSP,因为ElectricDuck需要的不仅仅是WildDuck或抽象Duck.但只要ElectricDuck提供没有额外要求的Quack方法,它就不是真的.
如果ElectricDuck要求电池发光 - 从LSP的角度看它是完全正确的:
public void Glow()
{
Contract.Requires(!this.Battery.IsEmpty);
}
Run Code Online (Sandbox Code Playgroud)
当我们将要求添加到继承方法时违反了LSP:
public override string Quack()
{
Contract.Requires(!this.Battery.IsEmpty);
return "electric quack";
}
Run Code Online (Sandbox Code Playgroud)
此修改将导致CodeContracts显示警告.
| 归档时间: |
|
| 查看次数: |
562 次 |
| 最近记录: |