C#在子类中隐藏受保护变量(或以其他方式解决问题)

时间:2012-04-18 19:28:06

标签: c# inheritance

我认为这不可行,但我很好奇。是否可以在其子类中的超类私有中创建受保护的变量。

例如,我有三个课程SuperClassSubClass : SuperClassSubCLass2 : SubClass

我希望能够访问来自protected string[] commands的{​​{1}}中的变量SuperClass,但阻止从SubClass访问它。

如果无法做到这一点,无论如何都能达到同样的效果吗?

4 个答案:

答案 0 :(得分:7)

  

我认为这不可行,但我很好奇。是否可以在其子类中的超类私有中创建受保护的变量。

没有。就个人而言,我会首先避免使用变量非私有 - 我提供受保护的属性。你可以创建一个新的属性来“隐藏”基本属性......但这对我来说是糟糕的设计。

我不能认为以任何方式绕过从大孩子的角度隐藏,而不改变其他类别之一,但对我来说这感觉很随意:

public class Base
{
    private int foo = 5;
    protected int Foo { get { return foo; } }
}

public class Child : Base
{
    protected new int Foo { get { return 0; } }
}

public class GrandChild : Child
{
    // Aargh, can't get at the original Foo...
}

为什么要实现这一目标?也许你应该密封你的直接子类,并强迫其他类使用组合代替......

编辑:正如评论中所解释的那样,听起来这是一个制作属性的情况(我仍然会使它成为返回私有字段的属性) internal 是合适的。这使得属性可以访问同一程序集中的所有其他代码,但不能访问其他程序集。

答案 1 :(得分:0)

我可以为您提供的下一个最好的事情(遵循Skeet已经解释过的)是让它更难以看到该物业。这不是很好 - 而不是我如何使用显式接口,但它是值得了解的。

 interface I
 {
   int Prop { get; set; }
 }

 class A : I
 {
   int I.Prop { get; set; }
 }

 class B : A
 {
   public void Bar()
   {
     (this as I).Prop = 2;
   }
 }

 class C : B
 {
   public void Foo()
   {
     //Prop = 1;
   }
 }

答案 2 :(得分:0)

我认为可以为变量创建一个容器,并在SubClass和SuperClass之间共享它,如下所示:

class Prop {
    public string Str = "a string";
}
class A {
    Prop prop;
    protected A(Prop p) { prop = p; }
    public A() : this(new Prop()) { }
}
class B : A {
    Prop prop;
    private B(Prop p) : base(p) { prop = p; }
    public B() : this(new Prop()) { }
}
class C : B {
    public void Meth() {
        // has no access to prop.Str
    }
}

答案 3 :(得分:0)

从C#的第1天开始,可以通过从基础隐藏成员来实现。特别是,您可以隐藏具有任何类型成员的成员。我觉得最自然的方法是在这种情况下隐藏字段,就是用一种方法将其隐藏。

public class Base
{
  protected int Foo;
}

public class Derived : Base
{
  // Current class can access base.Foo.
  public Derived() { base.Foo = 1; }
  // Hide base.Foo for further derived classes.
  [EditorBrowsable(EditorBrowsableState.Never)]
  [Obsolete("This is used to turn a protected field into private.", true)]
  protected new void Foo() { throw new FieldAccessException(); }
}

public class FurtherDerived : Derived
{
  // In this scope, base.Foo resolves to the method Derived.Foo.
  // If you try calling it, the compiler complains.
  // It is also impossible to say base.base.Foo.
}