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
将仍然能够访问这些受保护字段。aunit
本身具有隐含的友谊语义。在同一单元
中声明的类型是彼此的“朋友”(类似于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
是我没有搜索的关键字,它会直接导致我得出这个结论。谢谢你指出这个例外。