通过上篇文章 继承的本质 深入介绍了继承过程中对象的的创建过程,相信对继承已经有了一个深入的理解,本文则详细剖析一下面向对象设计的另一要素多态(Polymorphsim)

什么是多态

官方MSDN上是这样描述的点此可查看原文连接

Polymorphism is a Greek word that means "many-shaped" and it has two distinct aspects:

At run time, objects of a derived class may be treated as objects of a base class in places such as method parameters and collections or arrays. When this occurs, the object's declared type is no longer identical to its run-time type.

Base classes may define and implement virtual methods, and derived classes can override them, which means they provide their own definition and implementation. At run-time, when client code calls the method, the CLR looks up the run-time type of the object, and invokes that override of the virtual method. Thus in your source code you can call a method on a base class, and cause a derived class's version of the method to be executed.

大体意思就是:

  • 在运行时,对象的类型可以和运行时类型不同,派生类在某些地方可以被替换成基类,如方法的参数,集合或者数组。
  • 基类可以定义或实现虚方法,派生类能够重写父类的虚方法,这就意味派生类可以提供他们自己的定义和实现。在运行时,当客户端代码调用这些方法,CLR查找对象的运行时类型,并调用重写的虚方法。因此,你可以使用基类类型调用方法,从而执行派生类的一个实现。ps:翻译的水平一般,大体意思应该写出来了 :)

总结一下就是:

  • 1.派生类(子类)可以以基类(父类)类型出现;
  • 2.在运行时,派生类(子类)以自己的方式来实现;
  • 3.派生类(子类)以基类(父类)的类型使用时,只能使用父类共有或重写的方法,即特有的属性和方法不可以使用;

通俗简单来说就是,声明的时候是基类的类型,而实例化(new)的是派生类,举个栗子

public class Food
{
private string name = "Food"; public virtual string GetName()
{
return name;
}
} public class Bread : Food
{
private string name="Bread"; public override string GetName()
{
return name;
}
} public class ButterBread : Bread
{
private string name = "ButterBread"; public override string GetName()
{
return name;
}
}

Food food = new Bread(); 当我们调用 food.GetName() 时,执行的是 Bread.GetName() 方法,得到的是 "Bread"。如果我们这么写Food food = new ButterBread();,当调用 food.GetName() 时,执行的则是 ButterBread.GetName() 方法,这就是多态,有没有很简单!允许同一个类型具有不同的行为,通过例子是不是比上文扯的一堆要更好理解。

一张图轻松GET多态本质

相信上图很直观的对比了Food food = new Bread();Bread bread = new Bread();之前的区别:二者唯一的不同是在堆栈上维护的Bread实例的地址引用类型不同,food是Food类型的,bread是Bread类型的,但是二者指向的GCHeap上的实例都是Bread类型的实例。简单说明下,TypeHandle(类型句柄)是指向加载该类型的相关元数据信息包括方发表,静态字段等。CLR再第一次加载类型的时候就会创建该类型的方法表,并按继承关系将所有父类的方法copy一份,重写的方法会使用自己的方法覆盖掉。所以多态实际上在运行时执行的还是具体实例化类型的方法表。分享下我一般这么理解:我们吃的是食物,而它是面包。说到底还是要看吃到的是啥。关于详细的LoaderHeap介绍可以参考文末参考链接。

一些思考

面对日渐复杂多变的业务需求,如何使我们的程序更灵活,易扩展,当然是面向抽象编程了,抽象即稳定的,而多态是我们得以实现这一原则的基础。同时掌握了继承多态之后,我们才能更好的学习和理解设计模式。另外发现:看英文的文章比看中文的更容易理解。大家尽量多看些英文的技术文章,不要怕!手边常备个词典就好。

参考

深入理解.net - 2.多态 Polymorphsim的更多相关文章

  1. 深入理解OOP(三):多态和继承(动态绑定和运行时多态)

    在前面的文章中,我们介绍了编译期多态.params关键字.实例化.base关键字等.本节我们来关注另外一种多态:运行时多态, 运行时多态也叫迟绑定. 深入理解OOP(一):多态和继承(初期绑定和编译时 ...

  2. 深入理解OOP(二):多态和继承(继承)

    本文是深入浅出OOP第二篇,主要说说继承的话题. 深入理解OOP(一):多态和继承(初期绑定和编译时多态) 深入理解OOP(二):多态和继承(继承) 深入理解OOP(三):多态和继承(动态绑定和运行时 ...

  3. Java基础之理解封装,继承,多态三大特性

    目录 封装 继承 多态 封装 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 代码理解 publ ...

  4. 看懂下面C++代码才说你理解了C++多态虚函数!

    #include <iostream> using namespace std ; class Father { private :  virtual void Say()  //只有添加 ...

  5. 理解Go的多态实现

    总结两点: 在Go中,定义一个interface类型,该类型说明了它有哪些方法.使用时,在函数中,将该interface类型作为函数的形参,任意一个实现了interface类型的实参都能作为该inte ...

  6. 理解java的 多态

    http://www.cnblogs.com/chenssy/p/3372798.html

  7. 深入理解OOP(四): 多态和继承(抽象类)

    在本文中,我们讨论OOP中的热点之一:抽象类.抽象类在各个编程语言中概念是一致的,但是C#稍微有些不一样.本文中我们会通过代码来实现抽象类,并一一进行解析. 深入理解OOP(一):多态和继承(初期绑定 ...

  8. 深入理解OOP(第一天):多态和继承(初期绑定和编译时多态)

    在本系列中,我们以CodeProject上比较火的OOP系列博客为主,进行OOP深入浅出展现. 无论作为软件设计的高手.或者菜鸟,对于架构设计而言,均需要多次重构.取舍,以有利于整个软件项目的健康构建 ...

  9. python中对多态的理解

    目录 python中对多态的理解 一.多态 二.多态性 三.鸭子类型 python中对多态的理解 一.多态 多态是指一类事物有多种形态,比如动物类,可以有猫,狗,猪等等.(一个抽象类有多个子类,因而多 ...

随机推荐

  1. C#编程语言之委托与事件(二)—— C#事件

    前面已经大致讲述了C#委托的一些基础知识点,本文接下来的内容是C#中的事件(Event),在此我提个建议,如果是刚接触C#的委托类型的朋友可以先看到这里,等熟悉了委托的使用之后(大约1-2天)再来了解 ...

  2. 用Python满足满足自己的“小虚荣”

    首先声明,学习这个只是为了好玩,只是为了好玩,并不是想用这个弄虚作假,做一些不好的事情!一心想做技术人,自制自治! 我们有时候发布一篇日志,或者是一篇博文,总希望自己的浏览量能高点,这样看起来也倍有面 ...

  3. 2017-2018-1 20155306 mypwd的实现

    2017-2018-1 20155306 mypwd的实现 一.pwd的使用 功能: Linux中用 pwd 命令来查看"当前工作目录"的完整路径. 命令格式:pwd [选项] 命 ...

  4. 201621123062《Java程序设计》第一周学习总结

    1.本周学习总结 关键词: 初步熟悉Java的基本组成.语言特点(简单性.结构中立性).运行环境.简单语法等. 关键概念之间的联系: 1.JVM是Java程序唯一认识的操作系统,其可执行文件为.cla ...

  5. C语言——第四次作业

    题目 题目一:计算分段函数 1.实验代码 #include <stdio.h> int main() { double x,y; scanf("%lf",&x) ...

  6. 团队作业7——第二次项目冲刺(Beta版本12.05-12.07)

    1.当天站立式会议照片 本次会议内容:1:每个人汇报自己完成的工作.2:组长分配各自要完成的任务. 2.每个人的工作 黄进勇:项目整合,后台代码. 李勇:前台界面优化. 何忠鹏:数据库模块. 郑希彬: ...

  7. velocity学习总结

    什么是velocity velocity是一个基于Java的模板引擎,它可以实现彻底的前后端,前端不允许像jsp那样出现Java代码,而是利用context容器传递变量,在java代码里面我们可以往容 ...

  8. ebtables和iptables与linux bridge的交互

    本文为翻译文,不一定是逐字逐句的翻译,而且中间会加上自己的一点见解,如有理解错误的地方,还请大家指出,我定虚心学习.原文见链接 其中斜体字是自己的理解,建议和ebtables手册和iptables手册 ...

  9. GitHub 上下载单个文件夹

    写代码的一定经常去github上查看.下载一些源码,有时候会想下载一个项目中的一个文件夹里的内容,但是github上只提供了整个项目的下载,而整个项目里东西太多,压缩的文件太大,github的下载速度 ...

  10. 智能合约语言 Solidity 教程系列9 - 错误处理

    这是Solidity教程系列文章第9篇介绍Solidity 错误处理. Solidity系列完整的文章列表请查看分类-Solidity. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文 ...