【问题标题】:Prevent calling base class implemented interface method in the derived class C#防止在派生类C#中调用基类实现的接口方法
【发布时间】:2015-05-22 10:33:46
【问题描述】:

是否可以在基类中实现接口并允许在第一个派生类级别调用/覆盖已实现的方法,但阻止从任何进一步的派生类调用它?

    public interface IInterfaceSample
    {
        bool Test();
    }

    public class Base: IInterfaceSample
    {
        public virtual bool Test()
        {
             return True;
        }
    }

    public class Sub1: Base
    {
        //I need to be able to override the Test method here
        public override bool Test()
        {
             return True;
        }
    }

    //Under a separate project:
    public class Sub2: Sub1
    {
       //I need to prevent overriding the interface implementation in this class
    }

现在我需要的是:

    var b = new Base();
    b.Test();//This should work

    var s1 = new Sub1();
    s1.Test();//I need this to work too

    var s2 = new Sub2();
    s2.Test();//I need to prevent doing this

到目前为止,我认为这可能是不可能的,因为接口必须是公共的,否则使用它们没有真正的价值。

就我而言,我需要 Sub2 类才能访问 Sub1 中的属性,但只能访问该类的方法,尤其是接口实现方法。

我能够做到这一点的唯一方法是根本不使用接口并这样做:

    public class Base
    {
        internal virtual bool Test()
        {
             return True;
        }
    }

    public class Sub1: Base
    {
        //I am able to override the Test method here
        internal override bool Test()
        {
             return True;
        }
    }

    //Under a separate project:
    public class Sub2: Sub1
    {
       //Nothing to override here which is what i need
    }

    var b = new Base();
    b.Test();//This works

    var s1 = new Sub1();
    s1.Test();//This works too

    var s2 = new Sub2();
    s2.Test();//This is prevented

但是我想知道这是否仍然可以通过接口实现,非常感谢任何帮助。

【问题讨论】:

  • 如果 Sub1 继承了接口,那么 Sub2 不需要继承接口的任何成员,因为它们已经通过 Sub1 继承。顺便说一下,你可以把接口做成内部的。
  • 在我看来您需要重新设计您的对象模型,如果子类不应该具有父类的某些功能,那么它应该是子类吗?如果您将Sub2 的实例传递给可以接受Base 的任何实例的方法会发生什么?
  • 我刚试过这个,但是 Sub2 仍然可以覆盖 Test 方法的实现,并且可以从 Sub2 类实例调用 Test 方法,我需要防止这两种情况。
  • 好点@TrevorPilley,但是,在我的情况下,将 Sub2 创建为 Sub1 的子项的唯一目的是共享属性结构而不共享其他功能和方法,Sub1 和 Sub2 将用于两个项目的不同端和不同端将在错误的地方访问,我只需要防止在另一个地方复制 Sub 1,只需从中删除方法即可实现我的目标。

标签: c# class interface base derived


【解决方案1】:

您希望Test 方法仅在Sub1 中可用,但仍与Sub2 共享相同的属性。这可以通过改变继承链来实现:

对此:

【讨论】:

    【解决方案2】:

    在 Sub1 中使用 sealed protected override bool Test()

    【讨论】:

    • 它仍然可以从 Sub2 调用 - 只是不可覆盖。
    【解决方案3】:

    不,这是不可能的——它会破坏多态性的全部意义。特别是,假设您没有使用var,而是明确使用了类型:

    Sub1 s2 = new Sub2();
    s2.Test();
    

    必须编译:

    • 必须编译第一行,因为Sub2 派生自Sub1
    • 第二行必须编译,因为您希望s1.Test() 编译,其中s1 的编译时类型也是Sub1

    根据经验,如果您有两个类 X 和 Y,并且只有 一些 X 上的公共操作对 Y 有效,那么 Y 不应派生自 X。您应该能够将派生类的任何实例视为基类的实例(以及它实现的所有接口)。

    【讨论】:

    • 谢谢@Jon,我明白你的意思,这是有道理的,我试图做的全部目的是防止重复属性结构并且必须一遍又一遍地维护它,我可以很容易地创建一个只有属性的重复类并使用它,但这会在以后引起很多麻烦,所以我想知道是否有一种方法可以通过继承来做到这一点,但阻止使用这些方法。
    • @Anas:老实说,我不太理解您的评论,关于“复制属性结构”-但确实感觉您可能应该为此使用组合而不是继承...
    • 对不起,如果我不够清楚,我需要在项目的两个单独层中有一个包含属性列表的类,例如 public class Class1 { public string P1 {get;set;} public string P2 {get;set;} public string P3 {get;set;} } 但是这个类有一些功能应该在一层而不是另一层中可用,所以我不想最终在两端复制类有细微的差别,因为它会增加维护它们的开销,以便在我们更改属性或其他东西时保持同步,如果我可以通过继承来做到这一点,那就太好了。
    • @Anas:听起来您应该将通用功能提取到单独的类型中-然后您可以使用组合使 Class1 具有 CommonProperties 引用,并为您的其他类提供同上。继承在这里合适。
    • 谢谢@Jon,关于继承,你提到它不合适,仅仅是因为你可以通过显式使用类型来扭转它,还是你有任何其他缺点介意吗?
    猜你喜欢
    • 2012-03-14
    • 2010-09-22
    • 2014-03-22
    • 1970-01-01
    • 2014-06-17
    • 2019-07-25
    • 2013-11-23
    • 2016-06-14
    • 2016-07-06
    相关资源
    最近更新 更多