首页 / 软件开发 / C# / Effective C#原则29:仅在对基类进行强制更新时才使用new修饰符
Effective C#原则29:仅在对基类进行强制更新时才使用new修饰符2010-12-11 博客园 Wu.Country@侠缘译你可以用new修饰符来重新定义一个从基类中继承来的非虚成员。你可以这样 做,但并不意味着需要这样做。重新定义非虚方法会导致方法含意的混乱。如果 两个相关的类是继承关系,那么很多开发人员可能会立即假设两段代码块是做完 全相同的事情,而且他们也会这么认为:object c = MakeObject( );
// Call through MyClass reference:
MyClass cl = c as MyClass;
cl.MagicMethod( );
// Call through MyOtherClass reference:
MyOtherClass cl2 = c as MyOtherClass;
cl2.MagicMethod( );
一但使用了new修饰符以后,问题就完全 不一样了:public class MyClass
{
public void MagicMethod( )
{
// details elided.
}
}
public class MyOtherClass : MyClass
{
// Redefine MagicMethod for this class.
public new void MagicMethod( )
{
// details elided
}
}
这样的实 际操作会让很多开发人员迷惑。因为当你在同一个对象上调用相同的函数时,一 定希望它们执行同样的代码。但实际上是,一但你用不同的引用来调用同名的函 数,它们的行为是不一样的,这感觉非常糟糕。它们是不一致的。一个 MyOtherClass类型的对象所表现的行为会因为你引用的方式不一样而有所不同。 这就是new修饰符用在非虚成员上的后果。其实这只是让你在类的名字空间中添 加了一个不同的方法(虽然它们的函数名是相同的)。非虚方法是静态绑 定的,不管哪里的代码,也不管在哪里引用,MyClass.MagicMethod() 总是严格 的调用类中所定义的函数。并不会在运行时在派生类中查找不同的版本。另一方 面,虚函数动态的。运行时会根据不同的类型对象调用不同的版本。建 议大家避免使用new修饰符来重新定义非虚函数,这并不要太多的解释,就像推 荐大家在定义一个基类时应该用虚方法一样。一个类库的设计者应该按照合某种 约设计虚函数。也就表示你期望任何派生类都应该修改虚函数的实现。虚函数的 集合就相当于是定义了一个行为的集合,这些行为是希望在派生中重新实现的。 设计默认的虚函数就是说派生可以修改类中的所有虚的行为。这确实是说你不想 考虑所有派生类可能要修改行为的分歧问题。相反,你可以把时间花在考虑把什 么样的方法以及属性设计成多态的。当然,只有它们是虚行为的时候才能这样做 。不要考虑这样会限制类的用户。相反,应该认为这是给类型的用户定义行为提 供了一个入口向导。有且只有一种情况要使用new修饰符,那就是把类集 成到一个已经存在的基类上时,而这个基类中已经使用了存在的方法名,这时就 要使用new了(译注:就是说基类与派生类都已经存在了,是后来添加的继承关系 ,结果在添加继承关系时,发现两个类中使用了同样的方法名,那么就可以在派 生类中添加一个new来解决这个问题)。因为有些代码已经依懒于类的方法名,或 者已经有其它程序集在使用这个方法。例如你在库中创建了下面的类,使用了在 另一个库中定义的BaseWidget:public class MyWidget : BaseWidget
{
public void DoWidgetThings( )
{
// details elided.
}
}