无法访问受保护的符号?

Cannot access protected symbol?

我得到

cannot access protected symbol TParent.Test

以下代码:

第 1 单元:

TParent = class
protected
  function Test: TParent;
end;

implementation

function TParent.Test: TParent;
begin
  Result := Self
end;

第 2 单元:

uses Unit1;

type

TChild = class(TParent)
end;

implementation

var c: TChild;
begin
  c := TChild.Create;
  c.Test.Test
end;

TChild 不应该可以访问 return 值吗?

c.Test;
c.Test

当然可以。

return 值 TChild 可访问的,但您要做的是通过 TChild 中的 TParent 访问它,这略有不同。

这样想。

c.Test 是 TParent,是吗?

现在假设您有一个像这样定义的 TParent

var 
  c: TChild;
  p: TParent
begin
  c := TChild.Create;
  p := c.Test;
  p.Test;
end;

这与您的代码完全相同。 p 应该能够访问测试吗?不,因为它受到保护(并且在不同的单元中)。

var 
  c: TChild;
....
c.Test.Test;

方法 TParent.Test 受保护,这意味着它可以在 TParent 的方法和派生自 TParent 的 class 的方法中访问。而且,此外,当调用其 class 定义在与调用代码相同的单元中的引用时,它是可访问的。

documentation是这样说的,我强调的是:

A protected member is visible anywhere in the module where its class is declared and from any descendent class, regardless of the module where the descendent class appears.

TChild 在您访问受保护成员的单元中声明的事实是理解这一点的关键。

在您的示例代码中,在 Unit2 中,当您编写 c.Test 时,对 Test 的调用不是从 TParent 或 [=40 的方法进行的=] 派生自它。但它是在 TChild 类型的变量上创建的,该变量在 Unit2 中声明,是调用该方法的单元。所以它是可见的。

然而,c.TestTParent 类型。并且因为 TParent 是在不同的单元中定义的,所以 Unit1c.Test.Test 不会编译。同样,此代码不会在 Unit2:

中编译
var
  p: TParent;
....
p.Test;