2010-08-11 40 views
9

为什么需要隐藏方法时使用新的关键字?为什么在隐藏方法时使用“new”?

我有两个类:

public class Parent 
{ 
    public void Print() 
    { 
     Console.WriteLine("Parent"); 
    } 
} 

public class Child : Parent 
{ 
    public void Print() 
    { 
     Console.WriteLine("Child"); 
    } 
} 

下面的代码产生给定输出:

Parent sut = new Child(); 
sut.Print(); 

输出:家长

Child sut = new Child(); 
sut.Print(); 

输出:儿童

我明白个在这可能是一个问题,如果它隐藏不是有意的,但有没有其他原因使用“新”(例外警告)?

编辑:

可能是我不清楚。这是同样的情况,如:

public void foo(Parent p) 
{ 
p.Print(); 
} 

被称为:

Child c = new Child; 
foo (c);c 
+0

您的意思是'父SUT =新的父();'? – Humberto 2010-08-11 13:10:50

+1

@Humberto,不,我认为他的榜样是健全的。 – 2010-08-11 13:16:46

+0

可能的重复[为什么我们需要新的关键字,为什么是默认行为隐藏和不重写?](http://stackoverflow.com/questions/3117838/why-do-we-need-the-new-关键字和为什么是默认行为 - 隐藏和不 - ov) – 2010-08-11 13:38:15

回答

14

不,但避免警告非常重要。由隐藏导致的错误可能会非常严重,并且在C++(它允许你这么做)之后,Java和C#都选择了两种不同的方法来阻止它们。

在Java中,不可能隐藏基类方法。如果你尝试去做,编译器会尖叫血腥的谋杀。

在C#中,有“new”关键字。它允许你明确地表示你想隐藏一个方法,如果你不使用它,编译器会警告你。许多开发人员将代码编译器设为不带警告的规则,因为警告可能是错误代码的标志。

毕竟,我从来没有使用隐藏。我会仔细考虑为什么我会考虑使用它,因为它的行为很奇怪,而且几乎从不是我想要的。

+1

清楚简单的事实。 – 2010-08-11 13:18:48

+0

同意,但有一种情况下您可能需要使用新的。我在下面的答案中描述它。 – 2012-03-23 02:00:38

2

因为它使得明确,你是故意躲在父母的方法,而不是覆盖它。当您不使用new时会有警告,因为您的子类的方法可能存在拼写错误,并且意外隐藏父方法会导致一些细微的错误。

5

如果您尝试使用继承,则应该在基类中创建方法virtual,并在子类中创建override

语言设计者已经决定,如果不使用这些关键字,则方法隐藏应该使用new关键字明确完成。

1

只需标记Parent的方法virtual。然后你会在你的孩子班上做public override void Print()

public class Parent 
{ 
    public virtual void Print() 
    { 
     Console.WriteLine("Parent"); 
    } 
} 

public class Child : Parent 
{ 
    public override void Print() 
    { 
     Console.WriteLine("Child"); 
    } 
} 

这样你得到真正的继承,你可以通过调用base.Print()

+0

很好的例子,但没有回答这个问题;) – 2010-08-11 13:28:48

+0

我害怕,但你说得对。 – 2010-08-11 13:43:36

2

叫父母从孩子Print()方法你将不得不使用new关键字,如果在基本相同的签名方法班级没有标注abstractvirtual

+0

和子类必须标记为覆盖 – 2010-08-11 13:18:33

+0

@卢卡斯,正好!我忘了那部分。 – 2010-08-11 13:30:56

1

为什么在隐藏方法时需要使用new关键字?

它是而不是必要的。 new这里唯一的功能是抑制警告。

问题可能是:为什么隐藏基类成员不是错误?

1

的答案,另外你的问题

可能是我没说清楚。这与 的情况是一样的:

public void foo(Parent p){ p.Print(); }这被称为:

孩子c =新的孩子; foo(c);

答案是foo(c)会输出Parent。隐藏父方法的方法将不会执行,如果您正在调用父类,如示例中所示。要获得Child的输出,您将需要使用虚拟并覆盖,如前面的答案中所述。

3

隐藏是一个坏主意。它使代码更混乱,你的意图不明确。编程语言是为了向编译器和其他程序员表达你的意图。如果没有新的关键字,不清楚您的意图是覆盖还是隐藏,或者您对基本方法无知。

还有一个万无一失的元素。 “用脚射击自己,你确定吗?确定/取消”。

真正的问题是为什么隐藏在首位。不允许隐藏的问题是,如果您从另一个程序集中的类派生并添加Foo()方法,然后更新其他程序集以添加Foo()方法,则不允许隐藏会破坏您的代码。

+0

同意,我还有另一个答案,扩大了Jon的评论。 – 2012-03-23 01:58:59

3

扩大在什么乔恩·汉纳说...

警告的一点是要告诉你有,你可能不知道的名称冲突。当你的警告,你应该做以下操作之一:

  1. 添加虚拟和覆盖到多态覆盖从基类中的方法
  2. 重命名你的方法,所以它的名字没有在该方法不再冲突
  3. 基类添加新搞清楚你打算隐藏方法

如果要扩展或细化在基类中的方法的行为,使用虚拟和覆盖,正如其他人在这里说。

如果您刚刚第一次编写您的方法,并发现您有名称冲突,您不知道,并且您的意图是覆盖而不是,只需重命名您的方法即可。

选项1或2通常是优选的。那么你应该什么时候采用选项3?

您使用选项3时,基类是不是你的代码。您无法为其添加虚拟选项。你需要新的典型场景是这样的:

你买一个第三方库。它有一个有趣的课程。您从类继承并添加原作者未提供的新方法。到目前为止,没有涉及隐藏或压倒一切。现在,您将收到库的第2版,并提供了一些您想要使用的新功能。作者为他们的类添加了一个新方法,并且它的名字与你在派生类中写的方法冲突。

如果你的方法是不是用得非常多,你应该将其重命名的方式进行,选项2.但是,如果有你的方法很多依赖,这将是非常具有破坏性的重新命名它。所以你添加新的说,即使你的方法和基类中的方法之间存在没有逻辑连接,即使它们碰巧具有相同的名称。你没有能力为基类中的方法添加一个虚拟,你也不想这样做。这两个方法是由不同的开发人员设计的,而且你的方法不会改进或扩展基类中的方法 - 当你编写你的时候,基类中的方法不存在。

所以,这是罕见的,你需要新的关键字,但是当你这样做,这是很重要的。

相关问题