Class 为什么嵌套类会让包含类访问子类';受保护的数据?

Class 为什么嵌套类会让包含类访问子类';受保护的数据?,class,delphi,scope,Class,Delphi,Scope,这个问题可能有点混乱,最好用一个例子来说明: 单元测试 接口 类型 TestClass=class() Splitter1:TcxSplitter; 过程方法(); 结束; 实施 使用 cxSplitter; //局部声明的子类型 类型 TcxSplitterAccess=类(TcxSplitter); 过程TestClass.SomeMethod() 变量 pos:整数; 开始 //浇铸前进入受保护的现场位置 pos:=TcxSplitterAccess(拆分器1).FPositionBefo

这个问题可能有点混乱,最好用一个例子来说明:

单元测试
接口
类型
TestClass=class()
Splitter1:TcxSplitter;
过程方法();
结束;
实施
使用
cxSplitter;
//局部声明的子类型
类型
TcxSplitterAccess=类(TcxSplitter);
过程TestClass.SomeMethod()
变量
pos:整数;
开始
//浇铸前进入受保护的现场位置
pos:=TcxSplitterAccess(拆分器1).FPositionBeforeClose;
结束;
请注意,在实现部分,有一个类型
tcxsplitteracess
被声明为
TcxSplitter
类的子类。在属于类
TestClass
的方法
SomeMethod()
中,将
TcxSplitter
对象强制转换到本地声明的
TcxSplitter访问
类,然后访问该对象上的受保护字段

<>这是一个让我吃惊的人,比如来自java、C++、C语言等语言背景的人,在这些语言中,只要你从对象的类型或继承的类型中进行保护,就可以访问对象中的受保护数据。例如,类
ClazzA
中的方法可以访问其他
ClazzA
对象的私有字段,因为访问是在类型级别而不是实例级别强制执行的。用这些语言在本地声明类不会让包含类访问本地类的受保护数据(edit:,正如注释中指出的,至少对Java来说,这实际上是不正确的)

然而,在本例中,类型
TestClass
通过首先强制转换到
TcxSplitter访问类型,直接访问
TcxSplitter
对象上的受保护字段。我很难找到关于为什么这个“把戏”有效的文档。Delphi处理访问级别是否与Java类语言有根本性的不同,是否允许这样的事情?不管怎样,为什么这个把戏有效


当我偶然发现这种行为时,我使用了一个嵌套的继承类来访问父类上的字段(这破坏了封装,我不应该这样做),在这里使用继承是不必要的。如果嵌套类不是从类继承的,而是定义了自己的受保护字段,
TestClass
将仍然能够访问这些受保护字段。

a
unit
本身具有隐含的友谊语义。在同一
单元
中声明的类型是彼此的“朋友”(类似于C++中的
朋友
),因此可以访问彼此的
私有
受保护
成员(但不是
严格私有
严格受保护
成员)

因此,在这种情况下:

  • TcxSplitter访问
    源于
    TcxSplitter
    ,因此
    TcxSplitter访问
    通过普通类继承继承
    TcxSplitter
    的所有
    受保护的
    (但不是
    private
    )成员
  • TestClass
    tcxsplitteracess
    在同一
    单元中声明,因此
    TestClass
    可以访问
    tcxsplitteracess
    的所有
    受保护的
    成员,包括
    TcxSplitter
    受保护的
    成员(以及受其祖先保护的
    成员)
  • FPositionBeforeClose
    TcxSplitter
    中受
    保护
因此,这就是为什么在将
Splitter1
对象强制转换为
tcxsplitteracess
时,
TestClass.SomeMethod()
能够访问
FPositionBeforeClose

Delphi文档中包括了这一点:


如果不查看TcxSplitter的源代码,就无法给出准确的答案。FPositionBeforeClose是真正私有的还是受保护的?我很确定,如果您在Java中创建类的后代,它可以访问受保护的fields@DaveNottage我深入研究了源代码,您是对的-
FPositionBeforeClose
实际上是一个protected成员。我已经更新了问题以反映这一点。但是,问题仍然存在-请注意,示例中受保护的成员是通过
TestClass
访问的,而不是通过
tcxsplitteracess
访问的。FWIW:Java和C都允许嵌套/内部类型访问包含类中的私有字段。Java还可以访问privatee内部类与包含类的成员。私有规则(非多态)与受保护的规则完全分开。-(C#),(Java)@user2864740我知道嵌套类可以访问包含类的私有数据,但情况正好相反。我不知道Java也可以这样做!如果是这样的话,那么可能只是因为这种模式没有那么不同寻常,我只是不知道而已。@SertacAkyuz啊,在这里要小心,因为有一个微妙的问题这与正常继承行为不同。访问受保护数据的不是
tcxsplitteracess
,而是
TestClass
访问
tcxsplitteracess
(扩展为
TcxSplitter
)上的受保护成员。
TestClass
包含(嵌套)定义,它实际上不是父项。
Strict
是我没有搜索的关键字,它会直接导致我得出这个结论。谢谢你指出这个例外。