【C#】OOP之多态那点事
看上面的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之多态那点事的更多相关文章
- 深入理解OOP(三):多态和继承(动态绑定和运行时多态)
在前面的文章中,我们介绍了编译期多态.params关键字.实例化.base关键字等.本节我们来关注另外一种多态:运行时多态, 运行时多态也叫迟绑定. 深入理解OOP(一):多态和继承(初期绑定和编译时 ...
- 深入理解OOP(二):多态和继承(继承)
本文是深入浅出OOP第二篇,主要说说继承的话题. 深入理解OOP(一):多态和继承(初期绑定和编译时多态) 深入理解OOP(二):多态和继承(继承) 深入理解OOP(三):多态和继承(动态绑定和运行时 ...
- 【C#】OOP之继承那点事
前言: 继承这点事,说多不多,说少不少,这里只描述了一些我认为的基础篇,望各位大神指教.本节参照了C#高级编程和Think in java对继承的描述,我个人认为OOP只是思想,故看明白一个就说通的, ...
- OOP & 模块化, 多态, 封装
OOP 面向对象编程 (OOP) 是用抽象方式创建基于现实世界模型的一种编程模式.它使用先前建立的范例,包括模块化,多态和封装几种技术. 在 OOP 中,每个对象能够接收消息,处理数据和发送消息给其他 ...
- PHP基础OOP(二) 多态
PHP 基础 多态 ====================多态是一种思想:从一个基类中派生,响应一个虚命令,产生不同的结果. 不同的对象执行相同的方法而产生不同的行 ...
- 深入理解OOP(四): 多态和继承(抽象类)
在本文中,我们讨论OOP中的热点之一:抽象类.抽象类在各个编程语言中概念是一致的,但是C#稍微有些不一样.本文中我们会通过代码来实现抽象类,并一一进行解析. 深入理解OOP(一):多态和继承(初期绑定 ...
- 深入理解OOP(第一天):多态和继承(初期绑定和编译时多态)
在本系列中,我们以CodeProject上比较火的OOP系列博客为主,进行OOP深入浅出展现. 无论作为软件设计的高手.或者菜鸟,对于架构设计而言,均需要多次重构.取舍,以有利于整个软件项目的健康构建 ...
- javascript大神修炼记(7)——OOP思想(多态)
读者朋友们大家好,今天我们就接着前面的内容讲,前面我们已经讲到了继承,今天我们就来讲OOP目前最后一个体现,那就是多态,因为javascript语言的灵活性,所以我们是没有办法使用接口的,所以这也给j ...
- C++继承和多态
继承 访问控制 基类的成员函数可以有public.protected.private三种访问属性. 类的继承方式有public.protected.private三种. 公有继承 当类的继承方式为pu ...
随机推荐
- oracle 判断中文函数
create or replace function func_chinese( p_str in varchar2, -- 输入的字符串 p_code in varchar ...
- Conway's Game of Life: An Exercise in WPF, MVVM and C#
This blog post was written for the Lockheed Martin Insight blog, sharing here for the external audie ...
- Oracle中group by用法
Oracle中group by用法 在select 语句中可以使用group by 子句将行划分成较小的组,一旦使用分组后select操作的对象变为各个分组后的数据,使用聚组函数返回的是每一个组的汇总 ...
- 在java项目中使用log4j的实例
测试log4j的项目结构 Log4j.properties的路径为 src/config/log4j Log4j.properties文件的内容 下面定义日志输出级别是 INFO,并且配置了2个 ...
- SQLSERVER建立MYSQL连接服务器
1. 在SQL SERVER端安装MYSQL的ODBC驱动 2. 在ODBC数据源添加MYSQL(控制面板\所有控制面板项\管理工具) 在用户DSN 和系统DSN添加配置驱动程序 注:字符集一定要和M ...
- SOA架构改造简单记录
前端支持PC.Mobile.H5三个平台 nginx做负载均衡,主备机,keepalived,检测脚本,master和slave切换时完成相关工作: web做集群,web仅仅是web,与后端服务模块采 ...
- hadoop的dfs工具类一个【原创】
开始没搞定插件问题,就弄了个dsf操作类,后面搞定了插件问题,这玩意也就聊胜于无了,还是丢这里算了. 首先是一个配置,ztool.hadoop.properties hadoop.home.dir=G ...
- akka cluster sharding source code 学习 (2/5) handle off
一旦 shard coordinator(相当于分布式系统的 zookeeper) 启动,它就会启动一个定时器,每隔一定的时间尝试平衡一下集群中各个节点的负载,平衡的办法是把那些负载较重的 actor ...
- [Z] 北大一牛人生物转申CS的经历
http://www.bdwm.net/bbs/bbscon.php?board=CIS&file=M.1367038121.A&num=626&attach=0&di ...
- The file 'MemoryStream' is corrupted! 的解决办法
The file 'MemoryStream' is corrupted! Remove it and launch unity again! [Position > ] 有时候我们会遇到这个报 ...