正如this question和these articles中所述,不允许以下内容:
public class A
{
protected virtual int X {get; private set;}
}
public class B : A
{
public int Add(A other)
{
return X + other.X;
}
}
因为如果是的话,你有这个:
public class C : A
{
protected override int X { get { return 4; } }
}
然后:
A c = new C();
B b = new B();
b.Add(c);
这是非法的,因为即使B
访问X
表示它知道C
具有所需的签名,仍然不允许实际访问会员。
到目前为止,这么好。但鉴于上述情况,我感到困惑的是为什么我能做到这一点:
public class A
{
protected virtual int X { get; private set; }
public int Add(A other)
{
return X + other.X;
}
}
因此,这个:
A c = new C();
A a = new A();
a.Add(c);
definition of the protected keyword说:
受保护的成员可以在其类和派生类实例中访问。
但现在C
上的受保护成员正在A
内访问,A
既不是“它的类”也不是“派生类实例”,而是父类。虽然protected
显然可以访问签名,但兄弟示例似乎表明单独这一点不应该足够,所以为什么{{1}}授予它访问该成员的权限?
答案 0 :(得分:5)
这由the specification定义:
在程序文本之外访问受保护的实例成员时 声明它的类,以及受保护的内部 实例成员在程序的程序文本之外访问 它被声明,访问需要通过 发生访问的派生类类型的实例。:
public class A
{
protected int x;
static void F(A a, B b)
{
a.x = 1; // Ok
b.x = 1; // Ok
}
}
public class B : A
{
static void F(A a, B b)
{
a.x = 1; // Error, must access through instance of B
b.x = 1; // Ok
}
}
在A中,可以通过A和A的实例访问x B,因为在任何一种情况下,访问都是通过一个实例进行的 A或从A派生的类。但是,在B中,不可能 通过A的实例访问x,因为A不是从B派生的。
这一点的全部内容是,我不希望任何类C
的人,虽然允许从我的班级A
派生,但是在班级{{1}中访问我的“内部”状态虽然它们都分享了它们是类B
的衍生物的事实。
答案 1 :(得分:4)
作为C
的作者,我可以选择我的基类。所以我找到A
,我已经阅读了它的文档,我知道它将如何以及为什么会调用我继承的protected
成员(当然,我有{{1}等选项保护我的构造函数来控制哪些类(如果有的话)可以从我的sealed
派生出来。这就是我真正需要考虑的事情(在反射/完全控制场景之外,但一旦反射出现在图片中,所有投注都将被取消)。
我不必担心的是其他人决定要调用这些C
方法。哪个(根据您提议的修改),他们只需创建自己的类protected
,就可以从B
派生出来。