C#中易混淆概念:解析里氏替换原则,虚方法

今天开始上班了。这几天研究学习了一下思维导图,感觉用它整理自己的知识非常的方便。所以,以后写博客完成一个知识点,都会用思维导图做一个总结。也能让大家对所要读的内容有一个整体的把握。

我用的思维导图软件是FreeMind(免费的,但是得装JDK),因为刚开始学习使用,很多操作技巧不是很熟练,做出来的导图估计也不是很好,希望大家见谅。

首先,里氏替换原则。

这是理解多态所必须掌握的内容。对于里氏替换原则维基百科给出的定义如下:

为什么子类可以替换父类的位置,而程序的功能不受影响呢?

当满足继承的时候,父类肯定存在非私有成员,子类肯定是得到了父类的这些非私有成员假设,父类的的成员全部是私有的,那么子类没办法从父类继承任何成员,也就不存在继承的概念了)。既然子类继承了父类的这些非私有成员,那么父类对象也就可以在子类对象中调用这些非私有成员。所以,子类对象可以替换父类对象的位置。

来看下面的一段代码:

我们运行打印出的结果是:

根据前面的构造函数的知识很容易解释这个结果。那么我们在Main()函数中添加如下的代码:

在访问的过程中,可以发现p只可以访问父类的say

而p1也只可以访问父类的Say方法

其实在上面的代码中,就满足了里氏替换原则。子类的Student对象,替换了父类Person对象的位置。

那么它们在内存中发生了些什么呢?如下图:

由上可以知道,当一个父类的变量指向一个子类对象的时候只能通过这个父类变量调用父类成员,子类独有的成员无法调用。

同理我们可以推理出,子类的变量是不可以指向一个父类的对像的

但是当父类变量指向一个子类变量的时候,可以不可以把父类的变量转化成子类的对象呢?看下图

关于引用类型的两种转换方式:

由上面的代码我们已经知道了一种转换,就是在变量钱直接加需要转换的类型,如下代码:

那么第二种转换方式就是使用as关键字,如下代码:

使用as关键字和第一种强制转换的区别就是,第一种如果转换失败会抛异常,第二种转换失败则返回一个null值。

思维导图总结如下:

 二,虚方法

使用virtual关键字修饰的方法,叫做虚方法(一般都是在父类中)。

看下面的一段代码:

紧接着在main()函数中添加如下的代码:

打印结果如下:

我们很明显的可以发现,第二个表达式满足里氏替换原则,p1.Say()执行的应该是父类的Say()方法,但是这里却执行了子类的Say()方法。

这就是子类使用override关键字的Say()方法覆盖了父类的用Virtual关键字修饰的Say()方法。

我们使用动态图片看一下调试过程,

①首先是没有使用任何关键字:

由上可以看出直接跳入父类,执行了父类的Say()方法;

②再看使用virtual和override关键字的动态调试图片,如下

可以看到直接到子类去执行override关键字修饰的Say()方法。

那么如果父类使用virtual关键字修饰,而子类没有重写该方法时会怎么样呢?如下面的代码:

执行结果如下:

所以,如果子类找不到override方法,则会回溯到该子类的父类去找是否有override方法,知道回溯到自身的虚方法,并执行。

虚方法知识总结的思维导图如下:

1 1 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部