防止在C#中重写方法

时间:2012-03-28 20:10:30

标签: c# c#-4.0 sealed

如何防止在派生类中重写方法?

在Java中,我可以通过在我希望防止被覆盖的方法上使用final修饰符来实现此目的。

如何在C#中实现相同的目标? 我知道使用sealed,但显然我只能将其用于override关键字?

class A
{
    public void methodA()
    {
        // Code.
    }

    public virtual void methodB()
    {
        // Code.
    }
}

class B : A
{
    sealed override public void methodB()
    {
        // Code.
    } 
}

因此,在上面的示例中,我可以阻止methodB()被派生自类B的任何类重写,但是如何阻止类B覆盖methodB()在第一个地方?

更新:当我发布此问题时,我错过了A类virtual声明中的methodB()关键字。纠正了它。

4 个答案:

答案 0 :(得分:26)

你不需要做任何事情。 virtual修饰符指定可以覆盖方法。省略它意味着该方法是'最终'。

具体而言,方法必须为virtualabstractoverride才能覆盖。

使用new关键字将允许隐藏基类方法,但它仍然不会覆盖它,即当您调用A.methodB()时,您将获得基类版本,但是如果您调用{ {1}}您将获得新版本。

答案 1 :(得分:17)

正如您所提到的,您可以使用sealed override

来阻止B类进一步覆盖MethodB
class B : A
{
    public sealed override void methodB()
    {
        Console.WriteLine("Class C cannot override this method now");
    }
}

使用sealed修饰符 override可防止派生类进一步覆盖该方法。

如果您不希望A类中的methodB被任何子类覆盖,请不要标记该方法virtual。只需删除它。 virtual关键字允许在子类中重写该方法

public void methodA()
{       
}

在您的课程中使用sealed关键字,以防止进一步覆盖课程

答案 2 :(得分:5)

在C#中,未标记为virtual的函数(其中还包括虚函数的覆盖)实际上已被密封且无法覆盖。因此,您的示例代码实际上不会编译,因为override关键字无效,除非在基类中有一个标记为virtual且具有相同签名的方法。

如果A.methodB()被标记为虚拟,那么您可以从A覆盖该方法,但是可以使用与您显示的sealed关键字完全相同的方式阻止它在间接导出的类中进一步覆盖。

要记住的一件事是,虽然可以防止方法覆盖,但方法隐藏却不能。鉴于你目前对A类的定义,B类的以下定义是合法的,你无能为力:

class B:A
 {
      public new void methodB()
            {
                    //code
            } 
  }

new关键字基本上“打破”继承/覆盖层次结构,因为它与这一方法有关;任何对B类的引用,被视为B类(或任何进一步派生类型)将使用B类中的实现并忽略A类中的实现,除非B的实现特别回调它。但是,如果您将类B的实例视为类A(通过强制转换或将其作为参数传递),则忽略“新”实现。

这与覆盖不同,其中被视为A类并且真正覆盖虚拟方法B的B类仍将使用B类覆盖该方法。还要了解方法隐藏是推断的(虽然你会得到编译器警告);如果在派生类中声明具有相同签名的方法并且未指定new或override,则将隐藏基类方法。

答案 3 :(得分:1)

在基类中,sealed关键字仅用于防止派生类,但在继承的类中,它可用于防止另一个继承的类覆盖该方法。

要防止覆盖基类方法,请不要将其指定为虚拟方法。在您提供的示例中,B类无法覆盖methodB,因为methodB未在原始类上标记为虚拟。

这将编译:

class A
{
    public virtual void methodA()
    {
        //code
    }
    public virtual void methodB()
    {
        //code
    }
}
class B:A
{
    public override void methodB()
    {
        //code
    } 
}

这不会:

class A
{
    public void methodA()
    {
        //code
    }
    public void methodB()
    {
        //code
    }
}
class B:A
{
    public override void methodB()
    {
        //code
    } 
}

EDITTED:澄清并更正了我关于密封关键字的原始陈述