里氏替换原则
1. 继承
通过继承,子类会拥有父类的一切属性和行为
父类出现的地方都可以由子类代替
子类出现的地方不能由父类代替
public class InheritTest { public static void Show() { { Console.WriteLine("*************************************"); Parent obj = new Parent(); obj.CommonMethod(); obj.VirtualMethod(); } { Console.WriteLine("*************************************"); Child obj = new Child(); obj.CommonMethod(); obj.VirtualMethod(); } { Console.WriteLine("*************************************"); //Child obj = new Parent(); obj是个子类,不可以赋值一个父类,子类出现的地方不能由父类代替 Parent obj = new Child();//obj是个父类,可以赋值一个子类,因为父类出现的地方都可以由子类代替 obj.CommonMethod(); obj.VirtualMethod(); /* D A 都是Child B. 都是Parent C. common child, virtual parent D. common parent, virtual child Parent obj = new Child(); 普通方法的调用,由编译时决定,由左边决定(Parent) 虚方法/抽象方法的调用,由运行时决定, 由右边决定(Child) */ } { Console.WriteLine("*************************************"); AbstractParent obj = new AbstractChild(); obj.AbstractMethod(); } { Console.WriteLine("*************************************"); AbstractChild obj = new AbstractGrand(); obj.AbstractMethod(); } } } public class Parent { public void CommonMethod() { Console.WriteLine("This is {0} CommonMethod1", this.GetType().Name); } public virtual void VirtualMethod() { Console.WriteLine("This is {0} VirtualMethod2", this.GetType().Name); } } public class Child:Parent { /// <summary> /// new 表示隐藏; 这这里有没有new都可以 /// </summary> public new void CommonMethod() { Console.WriteLine("This is {0} CommonMethod3", this.GetType().Name); } /// <summary> /// override表示覆写 /// </summary> public override void VirtualMethod() { Console.WriteLine("This is {0} VirtualMethod4", this.GetType().Name); } } public abstract class AbstractParent { public abstract void AbstractMethod(); } public class AbstractChild:AbstractParent { public override void AbstractMethod() { Console.WriteLine("This is {0} AbstractMethod1", this.GetType().Name); } } public class AbstractGrand:AbstractChild { public override void AbstractMethod() //可以被override多次,这里用new就变成普通方法了 { Console.WriteLine("This is {0} AbstractMethod2", this.GetType().Name); } }
2. 里氏替换原则(Liskov Substitution Principle LSP)
A .所有使用基类的地方,都可以使用其子类来代替,而且行为不会有任何改变
B. 如果子类不拥有父类的全部属性或者行为,不能继承,断掉继承
C. 子类可以拥有父类没有的属性或者行为,子类出现的地方,父类不能代替
namespace LSP { public class Chinese { public string Name { get; set; } public int Id { get; set; } public void Drink() { Console.WriteLine("{0} 中国人喜欢喝酒", this.GetType().Name); } public void Entertainment() { Console.WriteLine("{0} 中国人喜欢娱乐", this.GetType().Name); } public void EatFlour(Dumplings flour) { Console.WriteLine("{0} 中国人喜欢吃饺子", this.GetType().Name); flour.Taste(); } } }
namespace LSP { public class Jiangxi:Chinese { public string waguntang { get; set; } //瓦罐汤 public void Larou() { Console.WriteLine("{0} 喜欢吃腊肉", this.GetType().Name); } //重载父类方法的时候要小心,很容易破坏里氏替换原则 public void EatFlour(Flour flour) //重载 { Console.WriteLine("{0} 喜欢吃所有面食", this.GetType().Name); flour.Taste(); } } }
class Program { static void Main(string[] args) { try { Flour flour = new Flour(); Dumplings dumplings = new Dumplings(); Wonton wonton = new Wonton(); { Console.WriteLine("*************************************"); Chinese pepole = new Chinese(); pepole.Drink(); pepole.Entertainment(); //pepole.EatFlour(flour); //错误 pepole.EatFlour(dumplings); pepole.EatFlour(wonton); } { Console.WriteLine("*************************************"); Chinese pepole = new Jiangxi(); pepole.Drink(); pepole.Entertainment(); //pepole.EatFlour(flour); //错误 pepole.EatFlour(dumplings); pepole.EatFlour(wonton); } { Console.WriteLine("*************************************"); Jiangxi pepole = new Jiangxi(); pepole.Drink(); pepole.Entertainment(); //这时候行为发生了改变,去调用子类的方法了,这个违背了里氏替换原则 pepole.EatFlour(flour); pepole.EatFlour(dumplings); pepole.EatFlour(wonton); } } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.ReadKey(); } } }