【问题标题】:How do you make members inaccessible to sub-derived classes?您如何使子派生类无法访问成员?
【发布时间】:2016-06-07 09:47:36
【问题描述】:

假设我有一个这样的基类:

public abstract class MyBaseClass
{
  protected void MyMethod(string myVariable)
  {
    //...
  }
}

然后我在单独的程序集中继承这个类:

public abstract class MyDerivedClass : MyBaseClass
{
  static readonly string MyConstantString = "Hello";
  protected void MyMethod()
  {
    MyMethod(MyConstantString);
  }
}

我现在想确保从MyDerivedClass 继承的任何其他类都无法访问MyBaseClass.MyMethod() 方法。 (澄清一下,我仍然希望能够不带参数地调用MyDerivedClass.MyMethod())

我尝试使用protected internal,但没有成功。

更新:我正在尝试这样做,因为我正在处理的应用程序有一堆使用基类的单独程序。有 5 种不同“类型”的程序,每一种都执行一个特定的、单独的功能,但它们都有一些我试图抽象到这个基类中的通用代码。通用代码 99% 相同,仅根据调用它的程序类型略有不同。这就是为什么我的基类在示例中采用了一个字符串参数,然后该参数在派生的基类中消失了,因为该类知道它执行角色 x,所以它相应地告诉它的基类。

【问题讨论】:

  • 您的意思是不想让他们调用它,还是不想让他们覆盖它?
  • @MatthewWatson 两者。
  • 你无法阻止它被调用。
  • 你不能那样做,基本上。你不能让一个成员只能被其他一个类访问。
  • 简单,让它private

标签: c# abstraction access-modifiers


【解决方案1】:

然后我会在MyDerivedClass 中使用组合而不是继承。所以这个类的所有派生类都不知道MyBaseClass 的方法。 MyBaseClass 类我会让包可见,因此无法使用它。

abstract class MyBaseClass
{
  void MyMethod(string myVariable)
  {
    //...
  }
}

abstract class MyDerivedClass
{
   static readonly string MyConstantString = "Hello";
   private MyBaseClass baseClass;

   MyDerivedClass(MyBaseClass baseClass) 
   {
       this.baseClass = baseClass;
   }

  protected void MyMethod()
  {
    baseClass.MyMethod(MyConstantString);
  }
}

类名当然要改。

【讨论】:

  • 委托可能是这里的方式,正确;但是,如果您只是在包含类中编写包装器(就像您使用仅调用 MyBaseClass.MyMethod() 的 MyDerivedClass.MyMethod() 演示的那样),那么整个目的就会失败。只有在包含类逻辑更复杂的情况下,委派才是一种解决方案,因此包装和包装之间没有简单的 1:1 关系。
【解决方案2】:

这不太可能。这可能表明您的对象设计可能有问题,但这不是 SO 的问题。

不过,您可以尝试一些更卑鄙的方法:

public abstract class MyBaseClass
{
  protected abstract string MyConstantString { get; }

  protected void MyMethod()
  {
    //...
  }
}

public abstract class MyDerivedClass : MyBaseClass
{
  protected override sealed string MyConstantString => "Hello";
}

或者,更典型的是,只使用构造函数来传递所需的参数:

public abstract class MyBaseClass
{
  private readonly string myString;

  protected MyBaseClass(string myString)
  {
    this.myString = myString;
  }

  protected void MyMethod()
  {
    //...
  }
}

public abstract class MyDerivedClass : MyBaseClass
{
  protected MyBaseClass() : base("Hello") {}
}

从MyDerivedClass 派生的类在任何一种情况下都无法更改参数,从继承的角度来看,第二种方法更好一些(基本上,该类型是对其祖先类型的参数的闭包)。

【讨论】:

  • 使用构造函数让我足够接近我想要的。我什至没有考虑构造函数!
【解决方案3】:

您不能阻止继承类调用此方法 - 您已将其设为 protected,因此您的意图是让继承自它的类可以直接访问它,或者通过另一个子类访问它。

如果你想保持继承,你能做的最好的就是如果子类在MyDerivedClass中调用它就抛出一个错误:

public abstract class MyBaseClass
{
    protected void MyMethod(string myVariable)
    {
        Console.WriteLine(myVariable);
    }
}

public abstract class MyDerivedClass : MyBaseClass
{
    static readonly string MyConstantString = "Hello";
    protected void MyMethod()
    {
        base.MyMethod(MyConstantString);
    }

    protected new void MyMethod(string myVariable)
    {
        throw new Exception("Not allowed");
    }
}

public class SubDerivedClass : MyDerivedClass
{
    static readonly string MyConstantString = "Hello";
    public void Foo()
    {
        MyMethod(MyConstantString);
    }
}

当SubDerivedClass中调用Foo()时,会在DerivedClass中调用MyMethod,会抛出异常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-30
    • 2019-01-20
    • 2013-10-21
    • 2012-03-05
    • 2015-12-30
    • 1970-01-01
    • 2010-12-19
    • 2012-08-29
    相关资源
    最近更新 更多