【C#】OOP之多态那点事

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

前言: 对菜鸟开发者的忠告:花一万个小时练习 Coding,不要浪费一万小时无谓地 Debugging(也就说看代码)

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

我们来看一下类的实现:

publicabstractclassInstrument

{publicabstractvoidPlay();

}publicclassGuitor : Instrument

{publicoverridevoidPlay()

{

Console.WriteLine(string.Format("Play {0}",this.GetType().Name));

}

}publicclassPaino : Instrument

{publicoverridevoidPlay()

{

Console.WriteLine(string.Format("Play {0}",this.GetType().Name));

}

}publicclassViolin : Instrument

{publicoverridevoidPlay()

{

Console.WriteLine(string.Format("Play {0}",this.GetType().Name));

}

}

View Code

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

classPRogram

{staticvoidMain(string[] args)

{

Guitor g=newGuitor();

g.Play();

Paino p=newPaino();

p.Play();

Violin v=newViolin();

v.Play();

Console.ReadLine();

}

}

View Code

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

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

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

直接看例子:

classProgram

{staticvoidMain(string[] args)

{

PlayInstrument(newGuitor());

PlayInstrument(newPaino());

PlayInstrument(newViolin());

Console.ReadLine();

}publicstaticvoidPlayInstrument(Instrument instrument)

{

instrument.Play();

}

}

View Code

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

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

staticvoidMain(string[] args)

{

Instrument instrument=newGuitor();

instrument=newPaino();

instrument=newViolin();

Console.ReadLine();

}

View Code

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

向上转型

staticvoidMain(string[] args)

{

Guitor gutior=newGuitor();

Instrument instrument=gutior;

Console.ReadLine();

}

View Code

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

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

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

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

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

总结一下:

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

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

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

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

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航