Dom*_*mus 5 delphi compiler-construction encapsulation class protected
这个问题来自于使用方法链接时出现的问题(流畅的界面),我认为这是它可能成为问题的唯一原因之一.
为了说明,我将使用方法链接的示例:
在单元A中:
TParent = class
protected
function DoSomething: TParent;
end;
Run Code Online (Sandbox Code Playgroud)
在单元B中:
TChild = class(TParent)
public
procedure DoAnotherThing;
end;
implementation
procedure TChild.DoAnotherThing;
begin
DoSomething.DoSomething
end;
Run Code Online (Sandbox Code Playgroud)
我想保持DoSomething过程受保护,只对类后代可见.
这不会编译,抛出一个
无法访问受保护的符号TParent.DoSomething
因为DoSomething返回一个TParent,后续的DoSomething调用是从另一个单元中的TParent对象发出的(因此保护启动并且函数无法访问).(谢谢David Heffernan的解释)
为了减少它的本质,像TParent(Self).DoSomething在TChild类中是不可能的.
我的问题:
既然编译器确实知道从子类中访问Self参数的副本,那么是否存在访问祖先的受保护方法的能力破坏封装的实例?我只是谈论从后代的类方法中取消引用类型化的Self .我知道在这个类之外,该参数当然不应该访问祖先的受保护方法(在另一个单元中).
同样,简而言之:当一个与Self参数相同的变量在其自身的一个类方法中被取消引用时,编译器是否允许它访问其父级的受保护方法是不安全的(就像Self参数本身一样) )?
这是一个非常理论上的问题,但如果编译器允许这样做,我会对编译代码或封装会产生任何负面影响感兴趣.
谢谢.
Ste*_*nke 10
protected表示您可以在自己的实例中访问这些方法.这并不意味着您可以在任何其他类型的实例上访问这些方法.
你可以打电话的原因DoSomething中TChild,因为只有Self访问其祖先的保护成员.
事实上,在这种特殊情况下,DoSomething方法的结果等于 Self编译器无法评估(除了一些静态代码分析,我怀疑其中有任何OOP语言编译器).
C++解决了这个问题,能够使TChild成为TParent的友元类,从而使它能够访问这些方法.
在Delphi中,如果将两个类放在同一个单元中,则可以获得该功能.如果您想将这两个类保留在自己的单元中,您仍然可以通过声明"cracker class"来使用该功能.只需创建一个继承自的类TParent并将其放入同一个单元中TChild.然后,您可以将结果转换为DoSomething该类并访问受保护的方法TParent.
type
TChild = class(TParent)
public
procedure DoAnotherThing;
end;
implementation
type
TParentAccess = class(TParent);
procedure TChild.DoAnotherThing;
begin
TParentAccess(DoSomething).DoSomething;
end;
Run Code Online (Sandbox Code Playgroud)
更新6.12.2017:
您还可以为您的TChild班级添加一个方法来模仿"朋友状态"(感谢Ken Bourassa).
type
TChild = class(TParent)
private
type
TParentAccess = class(TParent);
function DoSomething: TParentAccess; inline;
public
procedure DoAnotherThing;
end;
implementation
function TChild.DoSomething: TParentAccess;
begin
Result := TParentAccess(inherited DoSomething);
end;
procedure TChild.DoAnotherThing;
begin
DoSomething.DoSomething;
end;
Run Code Online (Sandbox Code Playgroud)
第三种可能性是使用类助手来使方法可访问.这具有易于重复使用的优点,因为您只需要将辅助单元添加到您有孩子TParent且需要访问权限的任何单元.
type
TParentHelper = class helper for TParent
public
function DoSomething: TParent; inline;
end;
implementation
function TParentHelper.DoSomething: TParent;
begin
Result := inherited DoSomething;
end;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
303 次 |
| 最近记录: |