关键字 "sealed" 与 "override" 的联合使用

28

在像下面这样的方法签名中,是否总是需要在 sealed 关键字后使用 override

public sealed override string Method1(){.....}

我的意思是,如果我想在基类中“封装”该方法而不进行覆盖,那么是否仍需要使用override关键字?

3个回答

49

只有在你覆盖(override)它的时候,才会对封装(seal)一个方法有意义。

这里发生的是以下情况:
您正在从基类覆盖一个方法(override),并告诉编译器从您的类派生的类不再允许覆盖此方法(sealed)。

如果该方法是在您的类中声明的新方法,并且您想要防止派生类覆盖它,则不要将其声明为虚拟的即可。

如果该方法在基类中声明但不可重写,则对其进行封装没有任何意义,因为它已经无法被重写了。


我并不是那个意思。我想知道的是,如果Myclass没有继承任何类,并且有一个我想要封闭的方法,这个方法在MyClass中没有被重写,而是第一次声明。 - Victor Mukherjee
3
如果您是声明该方法的人,那么您已经拥有了完全的控制权。如果您不想让它在派生类中被重写,只需不将其定义为虚函数即可。请参见我的回答中倒数第二段。 - Daniel Hilgarth
好的,明白了。抱歉,我忘记了这个虚拟的东西,因为我只会Java,最近才开始尝试C#。 - Victor Mukherjee
2
@VictorMukherjee:是的,这是一个重要的区别:在Java中,方法默认是虚拟的,你需要通过final关键字显式声明它们为非虚拟的。而在C#中则相反:默认情况下,方法是非虚拟的,你需要通过virtual关键字显式声明它们为虚拟的。 - Daniel Hilgarth
还有一种抽象方法,类似于虚方法,但是必须被重写。 - Olivier Jacot-Descombes

5
我认为Hilgarth先生在这里给出了最好的答案,但是作为一个具有Java背景的程序员(比如我自己),我认为大多数新接触C#的程序员往往会将sealedJava中的final混淆,涉及到重写部分。
Java中,如果没有指定任何修饰符,方法的默认行为是该方法可以在其派生类中被覆盖。
而在C#中,默认行为是除非使用virtual关键字明确指定,否则该方法不能被重写。
希望这能对上面最好的答案进行补充。

0

技术上讲,这是可能的...但是,在我看来,解决方案有点不太干净。

想象一下你有一个类 A(可以是你的代码库中的类或外部库中的类):

public class A
{
    public virtual void M () { /* implementation */ }
}

你可以按照以下方式定义一个(抽象)类B : A
public class B : A
{
    public sealed override void M() => base.M();
}

任何类 C : B 都无法覆盖 A.M,因为您已经封闭了该方法(即使您没有进行语义更改)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接