繁体   English   中英

C#防止基类方法被派生类中的new修饰符隐藏

[英]C# prevent base class method from being hidden by new modifier in the derived class

这是我的情况。 在 Java 中,我可以在基类/超类中将方法标记为 final,派生类无法屏蔽具有相同签名的方法。 然而,在 C# 中,new 关键字允许继承我的类的人创建具有相同签名的方法。

请参阅下面的示例。 我需要保持orignal.MyClass公开,所以请不要建议作为答案。 这似乎是从 Java 迁移到 C# 时丢失的特性:

public class orignal.MyClass{
    public void MyMethod()
    {
     // Do something
    }
}

class fake.MyClass: orignal.MyClass {
    // How to prevent the following
    public new void MyMethod()
    {
     // Do something different
    }
}

编辑:不是重复的。

所有答案似乎都表明,不可能防止方法在派生类中被隐藏/隐藏。 在将一些旧的 Java 代码迁移到 C# 时,这一点变得很明显。 Java 中的 final 方法不允许任何人在任何派生类中使用相同的方法签名。 虽然在大多数情况下 C# 允许派生类中具有相同签名的方法很好,但如果有必要,防止这种行为会很好。

// 如何防止以下情况

没有办法阻止这种情况。 这是语言允许的。

请注意,在实践中,这并不重要。 如果你希望你的基类被用作你的类,你的方法仍然会被调用。 使用new仅在使用声明为DerivedClass的变量中的DerivedClass时隐藏该方法。

这意味着,如果您的 API 围绕MyClass构建,则在将实例传递到您的方法时仍将始终调用MyMethod


根据评论进行编辑:

如果您担心人们一般将您的课程子类化,那么您唯一真正的选择就是密封您的课程:

public sealed class MyClass
{

这将阻止人们完全创建子类。 但是,如果您想允许人们从您的类派生,则无法阻止他们将您的方法隐藏在他们的类中。

您无法阻止公共方法或属性被屏蔽,但您为什么要这样做呢? 这需要扩展基类的人故意采取行动(即他们需要输入new ),所以他们打算这样做,为什么要阻止他们呢?

也许你需要稍微改变一下你的模式? 如果扩展程序必须使用您的基本方法,那么您可以在其中放入一些关键的东西,从而迫使他们调用它。 当然,如果没有正确完成,这很臭,所以如果你使用这种方法,然后将你的方法标记为virtual ,那么在文档(或方法标题注释)中提到必须调用基本方法。 这样你就可以避免扩展器不得不隐藏/屏蔽你的方法(尽管他们仍然可以),但如果他们愿意,他们仍然可以扩展它。

我假设您真的想阻止某人覆盖该方法 - 无法阻止使用new隐藏方法,但它不会对基类构成风险,因此这不应该成为问题。

在 C# 中,方法默认情况下是不可覆盖的。 因此,您可以通过不将其标记为virtualabstract来简单地防止某人覆盖基本方法。 在 Java 中,方法默认是虚拟的,因此必须使用final来密封方法以防止被覆盖。

我认为唯一的方法是创建接口并将您的方法定义放入其中,然后让原始类实现接口并显式实现方法:

    interface IAnimal
    {
        string diary(string notes, int sleephours);   
    }

    class Dogs:IAnimal
    {        

virtual public string voice()
        {
            string v = "Hao Hao"; return v;
        } 
        string IAnimal.diary(string notes,int sleephours)
        {
            return notes + sleep.ToString() + " hours";
        }

    }

    class Cats:Dogs
    {
        public override string voice()
        {
            string v = "Miao Miao"; return v;
        }
    }

您不会通过 Cats 实例使用 diary() 方法。

为了防止隐藏基类方法,您可以这样做:

public class Org
{
    public void Do()
    {
        // do something
    }
}

public class Fake : Org
{
    public new void Do()
    {
        base.Do();
        // do something
    }
}

这里的 base 关键字指的是父类。 现在你在子类中调用了父类(这里是 Org)的方法,现在这个方法不再隐藏了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM