看上面的UML图,我们创建一个抽象的Instrument类,类中有一个抽象方法paly,然后所有的子类都继承这个类并实现paly方法。(若不懂继承,请参照另一篇:OOP之继承那点事

我们来看一下类的实现:

    public abstract class Instrument
{
public abstract void Play();
} public class Guitor : Instrument
{
public override void Play()
{
Console.WriteLine(string.Format("Play {0}", this.GetType().Name));
}
} public class Paino : Instrument
{
public override void Play()
{
Console.WriteLine(string.Format("Play {0}", this.GetType().Name));
}
} public class Violin : Instrument
{
public override void Play()
{
Console.WriteLine(string.Format("Play {0}", this.GetType().Name));
}
}

在每个子类方法里,我们直接出去字符串。

  class Program
{
static void Main(string[] args)
{
Guitor g = new Guitor();
g.Play(); Paino p = new Paino();
p.Play(); Violin v = new Violin();
v.Play(); Console.ReadLine();
}
}

在Main方法里,我们创建了三个对象,然后分别输出。 这个说在我们还没开始多态之前的写法,好麻烦有木有(木有?蹲角落写100个乐器的paly).那什么是多态呢?

什么是多态:一种形态的多种表现形式(好抽象...)

THINK IN JAVA上写到:多态是消除类型之间的耦合关系(还是很抽象)

  直接看例子:

    class Program
{
static void Main(string[] args)
{
PlayInstrument(new Guitor());
PlayInstrument(new Paino());
PlayInstrument(new Violin()); Console.ReadLine();
} public static void PlayInstrument(Instrument instrument)
{
instrument.Play();
}
}

  这样的输出是和上面的例子是一样的,我们改变了什么,我们提供了一个方法,把3个子类的引用放了进去,呀,为什么PlayInstrument的形参是Instrument的对象,这就是多态的关键之处,

我总结了一句话:子类的引用(new Guitor())指向父类的对象(Instrument instrument) ;

  

       static void Main(string[] args)
{
Instrument instrument = new Guitor();
instrument = new Paino();
instrument = new Violin(); Console.ReadLine();
}

   这个好神奇有木有,我初学时间也觉得,这个好神奇,这个这么玩的,让我来带领大家进入神秘的多态空间。

  

  

  向上转型

     

       static void Main(string[] args)
{
Guitor gutior = new Guitor();
Instrument instrument = gutior; Console.ReadLine();
}

向上转型,就说把子类的类型转成父类的,这样是安全的,看上面的例子,如果在VS IDE工具中查看,是没有编译报错的,这时为什么呢?我们来看张图。

这个圆我们把他当作堆(heap)来看,(这没有画栈,因为指向讨论向上转型的安全).我们来看一下Guitor里面包含了Instrument的所有的东西(除了构造,如果说你点不出来私有化的东西,你可以尝试用反射,它的确存在) ,这样我们把大块变成小块是不是很安全呢,因为我大块拥有小块里面所有的东西,所以说向上转型是安全的。

  

注:相反来说,向下转型是危险的,因为小块变成大块,你不可以控制里面的东西。(协变和逆变概念也差不多,我比较喜欢叫成和谐的变->安全,逆天的变->危险)

这样的话,我们把大块转换成小块(Instrument instrument=new Guitor()),我们只能调用到小块的东西了(所以我们在设计的时候,一般会用接口去限定)

  

  接口其实是应该单独拉出来谈的,但是由于接口基本概念不多,只是在我们OO设计中,接口用处很大,这里属于设计范围,在多态中,用接口做父类和用类写法一样的,可以去试试。

  

  总结一下:

  1.向上转型以后,虽然引用还是原本的子类,但是只能用父类的方法了(想想大块变小块)

  2.父类方法被子类重写了(virtual,override)以后,向上转型以后,调用相同的方法还是大块的(因为小块的被重写了,这样说感觉很牵强,因为如果我们在子类中用base关键字还是能调用父类的同名方法,至于这块的内存的调用,我一直没找到相关资料,如果有人知道,请分享一下,万分感谢)。

  3.接口和抽象类(类)在使用多态的上面是同一个形式

  

  感觉这边写的不好...望大家补充和指出不足,谢谢了。

【C#】OOP之多态那点事的更多相关文章

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

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

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

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

  3. 【C#】OOP之继承那点事

    前言: 继承这点事,说多不多,说少不少,这里只描述了一些我认为的基础篇,望各位大神指教.本节参照了C#高级编程和Think in java对继承的描述,我个人认为OOP只是思想,故看明白一个就说通的, ...

  4. OOP & 模块化, 多态, 封装

    OOP 面向对象编程 (OOP) 是用抽象方式创建基于现实世界模型的一种编程模式.它使用先前建立的范例,包括模块化,多态和封装几种技术. 在 OOP 中,每个对象能够接收消息,处理数据和发送消息给其他 ...

  5. PHP基础OOP(二) 多态

    PHP 基础  多态  ====================多态是一种思想:从一个基类中派生,响应一个虚命令,产生不同的结果.                不同的对象执行相同的方法而产生不同的行 ...

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

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

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

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

  8. javascript大神修炼记(7)——OOP思想(多态)

    读者朋友们大家好,今天我们就接着前面的内容讲,前面我们已经讲到了继承,今天我们就来讲OOP目前最后一个体现,那就是多态,因为javascript语言的灵活性,所以我们是没有办法使用接口的,所以这也给j ...

  9. C++继承和多态

    继承 访问控制 基类的成员函数可以有public.protected.private三种访问属性. 类的继承方式有public.protected.private三种. 公有继承 当类的继承方式为pu ...

随机推荐

  1. Android TextUtils类介绍

    对于字符串处理Android为我们提供了一个简单实用的TextUtils类,如果处理比较简单的内容不用去思考正则表达式不妨试试这个在android.text.TextUtils的类,主要的功能如下: ...

  2. windows server 2003 ODBC数据源配置错误

    1.ODBC 数据源链接失败,错误 :STATE hy000, 不能产生SSPI上下文, 2.文件服务器,TCP/IP协议属性中,DNS没有填写,填入DNS即可解决.

  3. RestTemplate 使用总结

    场景: 认证服务器需要有个 http client 把前端发来的请求转发到 backend service, 然后把 backend service 的结果再返回给前端,服务器本身只做认证功能. 遇到 ...

  4. netbeans项目中排除node_modules文件夹

    由于项目中的javascript使用了gulp编译技术,所以在web目录下有js的源码目录,其中又有gulp所使用的nodeJS模块,node_modules下面小文件很多,所以造成netbeans扫 ...

  5. 【转】你真的了解word-wrap和word-break的区别吗?

    原文在这里: http://www.cnblogs.com/2050/archive/2012/08/10/2632256.html

  6. cordova 学习笔记

    0.sdk安装 http://spring.io/guides/gs/android/ 1.安装(node.js 需要安装https://nodejs.org/) on OS X and Linux: ...

  7. 数据库时间createtime字段 数据类型的选取

    之前是一直在用datetime类型(db)精度到yyyy-MM-dd HH:mm:ss 或者 date类型 精度到 yyyy-MM-dd 用了框架自动注入功能,自己也没去深入没去管他的set赋值值等等 ...

  8. Android之线程回掉更新ui

    一:工作线程中的回掉更新UI public class MainActivity extends AppCompatActivity { private int i; private Callback ...

  9. 在Sharepoint2010中一种自定义调查列表的不允许再次答复提示的处理方法!

    在Sharepoint中默认创建的调查列表系统只允许答复一次,再次答复将报错误信息,这对最终用户而言是非常不友好的体验,当然你也可以在调查设置中的常规设置中设置允许多次答复,这样就会有错误提示信息,但 ...

  10. ps裁剪圆角

    1.打开要编辑的图片 2.选择圆角矩形工具,并调整半径(半径越大,角越圆),本例半径为20像素 3.使用上述工具画出选区 4.按下ctrl+enter,可以看到选区边缘描上了虚线 5.菜单栏-图像-剪 ...