Delphi中“strict private”和“protected”访问修饰符之间的区别是什么?

22

在学习编程之前,我学过Pascal语言的结构化编程,现在开始学习Delphi中的面向对象编程。

因此,我不太理解strict private指令和protected指令之间的区别。这是我的代码,它是关于创建“包裹”的,只是我的Delphi课程介绍的一部分,老师向我们展示了如何创建对象:

    uses
  SysUtils;

Type

  Tbag= class (Tobject)                                                          
    strict private                                                                
      FcontenM : single;
      Fcontent : single;
    protected
      function getisempty : boolean;
      function getisfull: boolean;
    public
      constructor creer (nbliters : single);
      procedure add     (nbliters : single);
      procedure clear   (nbliters : single);
      property contenM : single read FcontenM;
      property content : single read Fcontent;
      property isempty : boolean read getisempty;
      property isfull : boolean read getisfull;
    end;


function Tseau.getisempty;
  begin
    result := Fcontent = 0;
  end;

function Tseau.getisfull;
  begin
    result := Fcontent = FcontenM;
  end;

constructor Tseau.creer(nbliters: Single);
  begin
    inherited create;
    FcontenM := nbliters;
  end;

procedure Tbag.add (nbliters: Single);
  begin
    if ((FcontenM - Fcontent) < nbliters) then fcontent := fcontenM
      else Fcontent := (Fcontent + nbliters);
  end;

procedure Tbag.clear (nbliters: Single);
  begin
    if (Fcontent > nbliters) then Fcontent := (Fcontent - nbliters)
      else Fcontent := 0;
  end;

那么这只是一个对象创建的示例;我理解什么是公共声明(可以被外部访问的接口),但我不明白私有和受保护声明之间的区别...感谢您试图帮助我。

5个回答

37
私有、受保护和公共之间的区别非常明显:
私有成员/方法只能在声明它们的类中可见。
受保护的成员/方法在类内可见,且可见于所有子类。
公共成员和方法对于所有其他类都是可见的。
在Delphi中存在一个“错误”,使得同一单元中的所有成员的可见性均为公共的。 "严格"关键字更正了这种行为,因此private实际上是私有的,即使在单个单元内也是如此。为了良好的封装性,我建议始终使用strict关键字。
示例代码:
type
  TFather = class
  private
    FPriv : integer;
  strict private
    FStrPriv : integer;
  protected
    FProt : integer;
  strict protected
    FStrProt : integer;
  public
    FPublic : integer;
  end;

  TSon = class(TFather)
  public
    procedure DoStuff;
  end;

  TUnrelated = class
  public
    procedure DoStuff;
  end;

procedure TSon.DoStuff;
begin
  FProt := 10;       // Legal, as it should be. Accessible to descendants.
  FPriv := 100;      // Legal, even though private. This won't work from another unit!
  FStrictPriv := 10; // <- Compiler Error, FStrictPrivFather is private to TFather
  FPublic := 100;    // Legal, naturally. Public members are accessible from everywhere.
end;

procedure TUnrelated.DoStuff;
var
  F : TFather;
begin
  F := TFather.Create;
  try
    F.FProt := 10;     // Legal, but it shouldn't be!
    F.FStrProt := 100; // <- Compiler error, the strict keyword has "made the protection work"
    F.FPublic := 100;  // Legal, naturally.
  finally
    F.Free;
  end;
end;

18
这不是一个漏洞,而是预期行为,VCL 在很大程度上使用它。 - Mason Wheeler
8
这就是为什么我写了“bug” :-) 这是Delphi的工作方式,但不是标准的面向对象编程。 - Svein Bringsli
13
那么,是谁定义了“标准面向对象编程”呢?我不知道是否有一些面向对象编程标准委员会。面向对象编程仅仅定义了一种围绕封装、继承和多态的范式。关于如何实现访问修饰符并没有严格(故意双关)的规定。为了更好地澄清,访问规则在单位级别上实现了隐式的“友元”,而不需要添加显式的语法来实现。 - Allen Bauer
7
好的,我改口了。可以这样说,Delphi的行为不符合“我的”面向对象编程标准吗?;-) 说真的,我认为根据类定义所在的文件来赋予不同的访问修饰符意义是一件坏事。最好使用某种友元声明(正如您所提到的)。 - Svein Bringsli
@Marco,strict是因为.NET兼容性需要。但它也有它的优点。 - Toon Krijthe
显示剩余4条评论

6

5

您可以在任何地方查找此信息(关键字应为“访问修饰符”)。

基本上,protected意味着成员在子类和整个单元中可见。严格私有意味着您仅能在该类的成员方法中访问该成员。


5
在其他答案中缺少一个案例:在其类内部的代码中,可以访问其他实例的私有字段,甚至是严格私有字段。请注意,这里保留了HTML标记。
type
  TSO1516493= class
  strict private
    A: Integer;
  public
    procedure ChangeOther(Param: TSO1516493);
  end;

{ TSO1516493 }

procedure TSO1516493.ChangeOther(Param: TSO1516493);
begin
  Param.A := -1; // accessing a strict private variable in other instance !
end;

(这与Java中的行为相同。)

3

其他答案中缺少的一个情况是,有可能会“扩展”类的封装规则。

通过类助手,在Delphi 8中引入(为了.NET兼容性),可以绕过私有、受保护和公共(甚至是严格的标记)之间的可见性差异。类助手声明可以在原始类所在的另一个单元中。

这是一个例子:

type
  TMyOrgClass = class
  strict private
    FMyPrivateProp: Integer;
  strict protected
    property MyPrivateProp: Integer read FMyPrivateProp;
  end;

  TMyClassHelper = class helper for TMyOrgClass
  private
    function GetMyPublicProp: Integer;
  public
    property MyPublicProp: Integer read GetMyPublicProp;
  end;

function TMyClassHelper.GetMyPublicProp: Integer;
begin
  Result:= Self.FMyPrivateProp;  // Access the org class members with Self
end;

请看这篇帖子了解更多信息:访问 Delphi 类的严格保护属性

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接