读书人

关于New关键字暗藏基类的用途的疑问

发布时间: 2013-01-23 10:44:50 作者: rapoo

关于New关键字隐藏基类的用途的疑问
本帖最后由 hymhblf 于 2013-01-12 08:48:34 编辑 对于New关键字,它有一个作用就是可以隐藏基类的方法,比如以下的代码:

 public class Car
{
public virtual void Start()
{
Console.WriteLine("车在启动。。。。。");
}

}
public class Train : Car
{
public void Start() //这个地方因为没有加New,所以会报一个警告
{
Console.WriteLine("火车在启动。。。。。");
}
}
public class Bicycle : Car
{
new public void Start()
{
Console.WriteLine("自行车在启动。。。。。");
}
}
class Program
{
static void Main(string[] args)
{
Car car = new Car();
car.Start();
Train train = new Train();
train.Start();
Bicycle bicycle = new Bicycle();
bicycle.Start();
car = (Car)bicycle;
car.Start();
Console.ReadLine();
}
}



它的输出结果如下:
车在启动。。。。。
火车在启动。。。。。
自行车在启动。。。。。
车在启动。。。。。

它的确是达到了隐藏基类的方法,但我现在有一个问题是,比如上面的代码:Bicycle bicycle = new Bicycle();我本类就是创建的子类,就是以它自己去调用自身的方法,它就应该是这样输出,所以在此我不明白它隐藏基类的意义何在?
[解决办法]
这样直接new ,违反了 里氏替换原则,直接改变基类的方法原有的行为。 这是不推荐的,如果要改变的话,请使用 虚或者抽象通过override来重写。
[解决办法]
比如说,你设计了一个叫快餐店的基类,里面允许调用可乐、汉堡、薯条等方法。
另外你有一个地名分区的类,里面有法兰克福、柏林、斯图加特等方法去汇总这些城市的数据。
现在问题来了,有个地方也叫汉堡,那么一个方法中就不得不出现两个汉堡,一个表示地方一个表示食物。他们没有任何关系,那么你就要使用new了。
[解决办法]
这个是为了跟微软自己的ms c++兼容,你不要过分遐想。

实际上这是一种垃圾设计,如果去除最好。但是市场强过与个人的爱好,在2000年、2001年那个时代,还是需要强调这些兼容性,所以才有了这种垃圾设计。

实践中,凡是有喜爱这种东西的,我们干脆就把程序员辞掉算了。
[解决办法]
以 lz 的代码作为例子,有这么一种情况
系统的原作者并不希望别人修改 Car 的 Start 行为,这时,此方法不会是 虚方法 或者 抽象方法。



随着系统的演变,出现了 Bicycle ,从概念上讲 Bicycle 与 Car 是一样的,都需要 Start,此时会 继承 Car,但是 Bicycle 的行为与 Car 是不一样的,所以原来的 Start 需要修改其行为,这时就会用到 new 关键字。

假如将 Bicycle 以 Car 的身份在原系统中运行,那么 Bycycle 的行为与 Car 的行为是一致的,而不是修改后的行为,这样就保证了 里氏替换原则 的实现。
这就是为什么 ((Car)bicycle).Start() 的结果依然是 “车在启动。。。。。”,而不是“自行车在启动。。。。。”的原因。

new 关键字的目的,就是为了保证原系统的行为不会因为子类的加入而发生改变,也就是“里氏替换原则”。

虚方法 和 抽象方法,他们的行为在子类中是可以修改的,这种修改将直接影响到父类(也就是原有系统逻辑),甚至出现子类在新系统中运行正常,而在旧系统中发生错误的可能性,所以这两种方法无法保证“里氏替换原则”的实现。

以上是个人对 new、虚方法 和 抽象方法的一些看法。

读书人网 >C#

热点推荐