【C#】OOP之多态那点事
2018-06-27 09:06:21来源:未知 阅读 ()
前言: 对菜鸟开发者的忠告:花一万个小时练习 Coding,不要浪费一万小时无谓地 Debugging(也就说看代码)
看上面的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.接口和抽象类(类)在使用多态的上面是同一个形式
感觉这边写的不好...望大家补充和指出不足,谢谢了。
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:ASP.NET中的事件处理
下一篇:Sql数据保存到Excel文件中
- Js 运行机制和Event Loop 2019-04-20
- Why ngx-uploader doesn't like to cooperate with 2018-11-09
- 微任务、宏任务与Event-Loop 2018-08-17
- JS运行机制(同步、异步、Event Loop) 2018-08-07
- 深入理解JavaScript的事件循环(Event Loop) 2018-07-29
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash