C#菜鸟之旅-----里氏替换
这是第二次学习“里氏替换”,因为经过了小组的讨论和自己今天的研究,感觉对于这个理解更深刻了,于是在学习完之后立刻整理,希望大家可以从这篇博客中有新的收获。
对于百度上“大话设计模式”书中对于“里氏替换”的概念都是:
**“派生类(子类)对象能够替换其基类(父类)对象使用” ,而且他们的功能并不会发生变化。**
但是为什么子类就可以替换父类,而且整个程序的功能不会受到影响呢?
**原因: 当我们写的关系满足继承的时候,父类中会存在非私有(非private)成员,这个时候,子类肯定是得到了父类的这些非私有成员(****假设,父类的成员全部都是私有的,那么子类没办法从父类继承任何成员,(这里有的网友也说是被继承了,只不过是无法访问)),****既然子类继承了父类的非私有成员,那么父类对象也就可以在子类对象中调用这些非私有成员。**
我们先来根据小杨老师看看他讲的“里氏替换”的四种转换的类型:
定义了一个父类 Person,俩个子类:分别是student ,teacher ,
Int num=10;
Double dou=num;
第一种:
Person P =new Teacher();
Teacher t =(Teacher) p ; //这是是强制转换
//如果 new的是子类 ,那么父类可以转换为子类 这样的是可以的
第二种:
Person p =new Person();
Student stu=(Student) p ;
//如果new的是父类,那么在转换子类的时候是不可以的
第三种:
Person p =new Teacher()
Student stu=(student)p;
//结果报异常,new的虽然是子类,但是转的却是另外一个子类;
//即new 的子类 和 转换的子类不是同一个类。
第四种:
子类转换成父类的时候就不需要强制转换,隐氏转换就可以了
Student stu=new student()
Person p =stu;
p.Show();
Console.readkey();
不会出现错误
通过上面小杨老师的讲解我们能够很清晰的清楚,在什么情况下我们才可以将父类替换成子类—-或者说是用子类来替换父类。
下面我们再来通过一个例子来研究一下“里氏替换”:
class Program
{
static void Main(string[] args)
{
Person p = new Person();
Person p1 = new Student();
Console.ReadKey();
}
}
class Person
{
//父类的私有成员
private int nAge;
public Person()
{
Console.WriteLine("我是Person构造函数,我是一个人!");
}
public void Say()
{
Console.WriteLine("我是一个人!");
}
}
class Student : Person
{
public Student()
{
Console.WriteLine("我是Student构造函数,我是一个学生!");
}
public void SayStude()
{
Console.WriteLine("我是一个学生!");
}
}
class SeniorStudent : Student
{
public SeniorStudent()
{
Console.WriteLine("我是SeniorStudent构造函数,我是一个高中生!");
}
public void SaySenior()
{
Console.WriteLine("我是一个高中生!");
}
}
运行后的结果是:
然后我们在Main()函数中添加一些代码其他的地方不改变:
static void Main(string[] args)
{
Person p = new Person();
p.Say();
Person p1 = new Student();
p1.Say();
Console.ReadKey();
}
继续运行,结果是:
而且在我输入代码的过程中,一个细节我发现,当我输入p.的时候,它后面的方法只有say,说明父类只可以访问父类的方法
在经过了
person p1=new student(); 之后 输入p1.的时候后面也只显示 say 方法。
所以这里就满足了里氏替换原则,子类的student 对象替换了父类person 对象的位置
二,虚方法中的里氏替换。
虚方法: 使用virtual关键字修饰的方法,叫作虚方法(一般都是在父类当中)
下面看一段关于虚方法的代码:
namespace ConsoleApp45
{
class Program
{
static void Main(string[] args)
{
Person p = new Person();
p.Say();
Person p1 = new Student();
p1.Say();
Student s = new Student();
s.Say();
Console.ReadKey();
}
}
class Person
{
private int nAge;
public Person()
{
Console.WriteLine("我是Person构造函数,我是一个人!");
}
//这里定义了一个虚方法
public virtual void Say()
{
Console.WriteLine("我是一个人!");
}
}
class Student : Person
{
//子类使用override关键字改写了父类的虚方法
public override void Say()
{
Console.WriteLine("我是一个学生!");
}
public Student()
{
Console.WriteLine("我是Student构造函数,我是一个学生!");
}
public void SayStude()
{
Console.WriteLine("我是一个学生!");
}
}
}
最终结果显示:
从上面的结果中可以看出,第二个表达式满足里氏替换原则,p1.say()执行的本该是父类的方法,但是却执行了子类的say方法
这就是子类使用override关键字覆盖了父类的虚方法
上面的这种情况是在父类的方法中写了“virtual” 同时子类中的方法也写了 override
那么如果父类中用 virtual修饰之后,而子类没有重写该方法。结果会是怎么样呢?
namespace ConsoleApp45
{
class Program
{
static void Main(string[] args)
{
Person p1 = new Student();
p1.Say();
Console.ReadKey();
}
}
class Person
{
private int nAge;
public Person()
{
Console.WriteLine("我是Person构造函数,我是一个人!");
}
//这里定义了一个虚方法
public virtual void Say()
{
Console.WriteLine("我是一个人!");
}
}
class Student : Person
{
//子类中没有出现override关键字修饰的方法
public void SayStude()
{
Console.WriteLine("我是一个学生!");
}
}
}
结果显示:
所以,如果子类中找不到 override 方法,就会回到子类的父类去找是否有 virtual并执行
还没有评论,来说两句吧...