假设我有3个班:GrandDad,爸爸,儿子。儿子继承自祖父,继承自祖父。
每个类都实现了foo。
// GrandDad class:
public virtual void foo()
// Dad class:
new public virtual void foo()
// Son class:
public override void foo()
我不明白为什么爸爸会使用 new 关键字。据我了解,使用 new 隐藏了一种方法。你为什么要这样做?
我阅读了新的MSDN解释,但讨论只是机械的,而不是架构的。
由于
答案 0 :(得分:3)
您提供的代码不是一个很好的示例,但“new”的一个常规用例是修改基类以添加新方法(通常是您无法控制的基类),但是您有现有代码需要使用相同的名称调用派生类方法。将派生类方法更改为“新”可以使您与公共接口的现有使用者保持兼容。
答案 1 :(得分:0)
希望以下示例为您提供了新关键字的用途。这实际上取决于功能的要求。
public class Base
{
public virtual void SomeMethod()
{
}
}
public class Derived : Base
{
public override void SomeMethod()
{
}
}
...
Base b = new Derived();
b.SomeMethod();
最终会调用Derived.SomeMethod,如果它重写Base.SomeMethod。
现在,如果您使用 new 关键字而不是覆盖,派生类中的方法不会覆盖基类中的方法,它只会隐藏它。在这种情况下,代码如下:
public class Base
{
public virtual void SomeOtherMethod()
{
}
}
public class Derived : Base
{
public new void SomeOtherMethod()
{
}
}
...
Base b = new Derived();
Derived d = new Derived();
b.SomeOtherMethod();
d.SomeOtherMethod();
首先调用Base.SomeOtherMethod,然后调用Derived.SomeOtherMethod。它们实际上是两个完全独立的方法,它们碰巧具有相同的名称,而不是覆盖基本方法的派生方法。
答案 2 :(得分:0)
当您在更多层(Control,Button,RedButton)上具有类的层次结构时,可能“有用”的场景,并且您希望限制给定类(Button)的任何子类以更改从Control继承的泛型行为,由Button修改;使用Button规则,而不是通过控制规则,RedButton可以成为TreeViewControl的其他方式:) ...;当您继承实现时会发生这种情况:)
还有其他技术,更干净,比如“策略模式”(您聚合行为,而不是继承)用于处理上一个场景。
答案 3 :(得分:0)
我将举一个超越“它做什么”的例子,并在它有用时予以掩盖。
您的业务类是否需要成为容器?例如,您可能想要这样做:
Person aperson = new Person();
aperson.Add(anAddress);
aperson.Add(anAddress);
如果您希望Add()方法在插入时执行某些特定于业务的逻辑,则可以选择。您可以自己实现容器功能(yuck),也可以让Person类继承容器:
public class Person : List<Address> { }
现在你可以在两个条件下得到你想要的行为:
新关键字是必需的,因为List.Add(...)不是虚拟的。这有点邪恶(可能很糟糕),但在这种特殊情况下大多很酷。在您编写的“new Add(...)”方法中,包含业务逻辑,然后调用基本的Add(...)方法。
想让它更酷吗?做一棵树:
public class Node : List<Node> { }
在电子游戏中,我在编写游戏树时使用了这个技巧。
答案 4 :(得分:-1)
这就是你想要这样做的一个原因:
// GrandDad:
public void CanIWatchTv() {
return age > 5;
}
// Dad: Grandpa is too liberal
public override void CanIWatchTv() {
return age > 12;
}
// Son: I don't care what dad says!
public new void CanIWatchTv() {
return true;
}
换句话说,当你完全想要覆盖(而不是关键字)基本方法正在做什么而不是扩展它时,你会使用new
。
在现实世界的场景中,它应该谨慎使用,因为它违背了继承原则(应Son
允许覆盖他的Dad
- 答案取决于你是儿子还是爸爸,但在一个完美的世界里,它不应该是。)
答案 5 :(得分:-1)
我的理解是,其中一个主要动机与图书馆的版本化有关。
1月1日: X公司将Class Dad作为Super Library v1.0的一部分发布。
class Dad
{
virtual public void Foo() { ... };
}
2月1日: 您购买Super Library v1.0并创建子类Son。
class Son : Dad
{
public void Bar() { ... };
}
3月1日: X公司发布了Super Library 2.0,添加了一个名为Bar的新方法。他们不知道你还创建了一个方法Bar,他们的Bar完全不相关。
class Dad
{
virtual public void Foo() { ... };
virtual public void Bar() { ... };
}
5月1日: 您购买Super Library v2.0并重新编译Son类。令您惊讶的是,您发现他们添加了一个名为Bar的方法与您的方法冲突。为了最大限度地降低回归风险,您现在将Bar方法标记为 new ,以区别于Company X的Bar。虽然他们奇怪地拥有相同的名字,但两者和平共存。他们现有的代码将按预期调用他们的Bar,现有代码将按预期调用您的Bar。
class Son : Dad
{
new public void Bar() { ... };
}