里式代换原则(Liskov Substitution Principle,LSP)
定义:
任何基类可以出现的地方,子类一定可以出现
里氏代换原则是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为
里氏代换原则是对开闭原则的补充,实现开闭原则的关键步骤是抽象化
而基类与子类的继承关系就是抽象化的具体实现
里氏代换原则是对实现抽象化的具体步骤的规范
简而言之就是:只要有父类出现的地方,都可以使用子类来替代。而且不会出现任何错误或者异常,但是反过来就不行。子类出现的地方不能用父类来替代
规范和约束:
子类必须实现父类的抽象方法,但不得重写父类的非抽象(已经实现的)方法
子类可以增加自己特有的方法
覆盖或实现父类的方法时输入参数可以被放大(方法的前置条件(方法形参)要比父类输入参数更加宽松。否则会调用到父类的方法)
覆盖或实现父类的方法时返回结果可以被缩小(抽象方法的后置条件(方法的返回值)要比父类更严格。否则会调用到父类的方法)
优点:
代码共享,减少创建类的工作量
提高代码的重用性、可扩展性
降低代码的灵活性,子类必须拥有父类的属性和方法
提高产品代码的开放性
示例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LSP.Study
{
public class Father
{
public void Display()
{
Console.WriteLine("这是父类");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LSP.Study
{
public class Children:Father
{
public new void Display()
{
Console.WriteLine("这是子类");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LSP.Study
{
/// <summary>
/// 里氏代换原则
/// </summary>
class Program
{
static void Main(string[] args)
{
Father father = new Father();
father.Display();
Children children = new Children();
children.Display();
}
}
}