子类型必须能够替换它们的基类性
如果对每一个类型为S的对象o1, 都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都替换成o2时, 程序P的行为没有变化, 那么类型s是类型T的子类型.
所有引用基类的地方必须能透明地使用其子类的对象.
里氏替换原则是实现开闭原则的重要方式之一, 由于使用基类对象的地方都可以使用子类对象, 因此在程序中尽量使用基类类型来对对象进行定义, 而在运行时再确定其子类类型, 用子类对象来替换父类对象.
// 里氏替换原则实例001
namespace 里氏替换原则实例001
{
public abstract class AbstractGun
{
public abstract void Shoot();
}
public class HandGun : AbstractGun
{
public override void Shoot()
{
Console.WriteLine("手枪射击");
}
}
public class Rifle : AbstractGun
{
public override void Shoot()
{
Console.WriteLine("步枪射击");
}
}
public class MachineGun : AbstractGun
{
public override void Shoot()
{
Console.WriteLine("机枪射击");
}
}
public class Soldier
{
public void KillEnemy(AbstractGun gun)
{
Console.Write("战士使用");
gun.Shoot();
}
}
public class ToyGun : AbstractGun
{
public override void Shoot()
{
Console.WriteLine("玩具枪");
}
}
public class G3 : Rifle
{
public void ZoomOut()
{
Console.WriteLine("望远镜查看敌人");
}
public void Shoot()
{
Console.WriteLine("G3射击");
}
}
public class Snipper
{
public void KillEnemy(G3 g3)
{
g3.ZoomOut();
g3.Shoot();
}
}
class Program
{
static void Main(string[] args)
{
Soldier hero = new Soldier();
hero.KillEnemy(new ToyGun());
hero.KillEnemy(new Rifle());
hero.KillEnemy(new HandGun());
Snipper snipper01 = new Snipper();
snipper01.KillEnemy(new G3());
// 父类代替子类可能会造成系统不稳定 不推荐
//Snipper snipper02 = new Snipper();
//Rifle rifle = new Rifle();
//snipper02.KillEnemy((G3)rifle);
}
}
}
// 里氏替换原则实例002
namespace 里氏替换原则实例002
{
public class A
{
public virtual int Func(int x,int y)
{
return x * y;
}
}
public class B : A
{
public override int Func(int x, int y)
{
return x - y; // 违法了里氏替换原则, 直接重写了父类的Func虚拟方法, 引用父类的地方并不能透明的使用子类的对象.
}
}
class Program
{
static void Main(string[] args)
{
B a = new B();
Console.WriteLine("10 + 5 = " + a.Func(10, 5));
A b = new B();
Console.WriteLine("10 + 5 = " + b.Func(10, 5));
}
}
}
namespace 里氏替换原则实例003
{
public class A
{
public int Func(int x,int y)
{
return x + y;
}
}
public class B : A
{
public int Func1(int x,int y)
{
return x - y; // 可以重新别的方法
}
}
class Program
{
static void Main(string[] args)
{
B b = new B();
Console.WriteLine("10 - 5 = " + b.Func1(10 ,5));
}
}
}
// 里氏替换原则实例004
namespace 里氏替换原则实例004
{
class Rectangle
{
int height, width;
public int GetWidth()
{
return width;
}
public void SetWidth(int width)
{
this.width = width;
}
public int GetHeight()
{
return height;
}
public void SetHeight(int height)
{
this.height = height;
}
}
class Square : Rectangle
{
int size;
public int GetWidht()
{
return size;
}
public void SetWidth(int width)
{
this.size = width;
}
public int GetHeight()
{
return size;
}
public void SetHeight(int height)
{
this.size = height;
}
public int GetSize()
{
return size;
}
public void SetSize(int size)
{
this.size = size;
}
}
class Program
{
// 调整
public static void TestRec(Rectangle rec)
{
int i = 0;
while (rec.GetWidth() <= rec.GetHeight())
{
rec.SetWidth(rec.GetWidth() + 1);
Console.WriteLine("循环次数: " + i++);
}
}
static void Main(string[] args)
{
Rectangle rec = new Square();
rec.SetWidth(5);
rec.SetHeight(1000);
TestRec(rec);
}
}
}