不要new你的函数

<p$1$2$3$4$5$6> 

c#有个new函数的语法,但是我觉得这个东西用途很少。很多时候容易出现设计上的错误。

<p$1$2$3$4$5$6> 

基类有个虚A()函数,子类不想覆盖,但是又想要这个名字,怎么办,那就是new A(){...}。

然后调用的时候,要想调用基类的,就用((基类)子类).A();要想用子类的,就子类.A();

<p$1$2$3$4$5$6> 

为什么说这个比较容易出现设计上的问题。

1.类继承系统的“界面”只能扩大,不能缩小

比如,你基类有个A函数,有个B函数,子类可以增加个C函数,但是不应该只是提供A函数,而没有B函数。这个不单是从语法上,还要从语义上能说得过去,这种通过多态调用和直接调用出现语义上差别的做法,必然隐藏很多出错的因素在里面。就好象成龙说的:你们看到是这样,用了也应该是这样的。

2.缩小都原因都是因为子类不是基类

我们知道设计继承关系有个很直观的法则:子类是基类。比如秋刀鱼是鱼。在设计过程中,如果出现要缩小,只能说一开始这个抽象依据就是错误的,比如鲸鱼不是鱼(如果鱼定义了鲸鱼所没有的界面)。

既然放弃了这个法则,那就属于滥用语法的范畴,而不属于面向对象的范畴。严格来说,就是简陋笨拙的复制粘贴行为。不是说不能用,只是没有设计上的优势罢了。

<p$1$2$3$4$5$6> 

如果非要用,怎么从设计上理解?

我的理解,这种在设计上的意义就是所谓的“实现继承”。也就是子类只是为了利用基类的实现为目的。但是这种方式,也许对于c#来说,用组合比用继承要好得多,为什么?因为c++ 有private继承,但是c#没有。

c++的私有继承,子类不能通过基类来调用,这样就根绝了多态调用的念头。

<p$1$2$3$4$5$6> 

----------------------------------------------------

想不到大家讨论的那么积极,下面对讨论做一些摘要(更新到80楼):

Zhenway:可以用new来改写同名返回函数的类型,比如把返回类型由基类改为子类类型,这在很多场景是有用的。

卡通一下:new未必和函数有关,也可以用在字段上,所以并不是只是针对多态的场景。(而原文只是讨论了多态的场景)

林静止水

我通常在以下情况下使用new
1.不能对虚方法是用new
2.对属性可使用new,并且是组合关系
3.比如某类a的属性是类b,类c继承类a,属性需要继承类b,新属性可以用new
新属性只完成强制转换

凌晨的太阳

记得VS的提示是这样的,当你企图用override来重写一个函数,或者直接编写一个函数的时候,如果该函数在基类中已被定义,并且没有virtual的时候,会提示使用new关键字。属性也可以使用new,情况差不多。
显然,new的使用和LZ的场景完全不同,概念也完全不同。

posted @ 2010-07-11 11:26  诺贝尔  阅读(4127)  评论(83编辑  收藏  举报