【问题标题】:property , getter and setter function not called未调用 property 、 getter 和 setter 函数
【发布时间】:2022-01-02 22:48:36
【问题描述】:

我认为DELPHI语言提供了一个非常清晰漂亮的数据封装实现 通过属性方法和清除 getter 和 setter 函数。

我想通过 getter 和 setter 函数访问类字符串列表 strlst。 代码示例中的选项 #1 可以正常工作,但选项 #2 调用 Stringlist.Commatext 函数实际上不起作用。

这是一个 DELPHI 错误还是我在类设计方面遗漏了什么?

目标:填充类stringlist而不创建外部Tstringlist类,只需传递commatext。

program Project2;
{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils, classes;

type
  TSimpleClass = class
    FStrlst: TStringList;

  private
    procedure SetStrList(const Value: TStringList);

  public
    constructor Create;

    property strlst: TStringList read FStrlst  write SetStrList;

  end;

  { TSimpleClass }

constructor TSimpleClass.Create;
begin
  inherited;

  FStrlst := TStringList.Create;

end;

procedure TSimpleClass.SetStrList(const Value: TStringList);
var
  i: Integer;
begin
  Writeln('class  getter / setter function is called ');
  for i := 0 to Value.Count - 1 do
  begin
    FStrlst.Add(Value[i]);
  end;

  writeln ('content of internal strlist : ' + FStrlst.CommaText )
end;

begin
  var
    aSimpleClass: TSimpleClass;
  var
    testLst: TStringList;

  try
    aSimpleClass := TSimpleClass.Create;
    try

       //   option #1  is working
      testLst:=TStringList.Create;
      testLst.CommaText := 'a,b,c';
      aSimpleClass.strlst := testLst;

     //    option #2  not working ...  this code should also call  the 
     //    setter function   
     aSimpleClass.strlst.commatext := 'd,e,f';


    finally
      aSimpleClass.Free;
    end;
    writeln ('done sample code !');
    Readln;

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

end.

命令行窗口示例输出

output of this sample code

【问题讨论】:

  • 选项 2 应该可以正常工作。你怎么知道它不起作用?您的代码没有在任何地方输出FStrlst 的数据。你期待SetStrList() 被调用吗?它不会,在选项 2 中,这很好。附带说明一下,您的代码正在泄漏FStrlst,因为TSimpleClass 缺少释放FStrlst 的析构函数。此外,SetStrList() 可以通过使用 FStrlst.Assign() 或 FStrlst.AddStrings(), instead of an Add()` 循环来简化。
  • 请。看看控制台输出。是的,我希望在选项 #2 中也调用了 setter,为什么不呢? (现在为 FStrlst 添加了输出选项)

标签: oop delphi


【解决方案1】:

这是一个 DELPHI 错误还是我在类设计方面遗漏了什么?

不,这不是 Delphi 错误,而是您的误解。您说“未调用属性、getter 和 setter 函数”,我理解您指的是 aSimpleClass.strlst 的 getter 和 setter。

您已经为TSimpleClass.strlst 定义了直接读取 访问(FStrLst),因此读取时没有要调用的getter(如// option #2),aSimpleClass.strlst 指的是直接到FStrLst

TStringListCommaText 属性有自己的设置器,在 // option #2 中调用


编辑

或者,如果您的意图是根本不公开 TStringList,而只公开其 CommaText 属性,则可以如下:

确保TStringList 是私有的,以及CommaText 的getter 和setter,并添加属性CommaTxt

TSimpleClass
private
  FStrlst: TStringList;
  ...
  function GetCommaText: string;
  procedure SetCommaText(s: string);
public
  property CommaTxt: string read GetCommaText write SetCommaText;
  ...
end;

实现getter和setter:

function TSimpleClass.GetCommaText: string;
begin
  result := FStrlst.CommaText;
end;

procedure TSimpleClass.SetCommaText(s: string);
begin
  FStrLst.CommaText := s;
end;

现在您可以在不暴露TStringList 的情况下访问CommaTxt 属性。

【讨论】:

  • 我只要求在选项#2中也调用setter函数,为什么不......
  • 在选项#1中,您将aSimpleClass.strlst设置为testLst,但在选项#2中,您根本没有设置aSimpleClass.strlst,而是在设置commatext属性。跨度>
  • 如果我误解了您的原始帖子,我添加了一个选项,即仅在您真正想要的情况下提供对 CommaText 属性的访问权限。
【解决方案2】:

option #2 不触发 setter 方法的原因是,在您的 option #2 中,您没有为您的 strlst 分配任何值,而是与所述属性返回的对象进行交互.

当您致电aSimpleClass.strlst.commatext := 'd,e,f'; 时,您会看到接下来会发生什么:

  1. 正在调用 strlst 属性的 Getter 方法以返回对 TStringList 对象(由属性定义的对象类型)的引用
  2. 然后将d,e,f 的字符串值分配给属于字符串列表的ComaText 属性,该字符串列表的引用由您的属性getter 方法返回。

现在,如果此时仍然没有创建属于您的类的 TStringList,则会引发访问冲突,因为您将尝试访问不存在的对象的属性。

【讨论】:

    猜你喜欢
    • 2011-01-09
    • 1970-01-01
    • 2012-02-25
    • 1970-01-01
    • 2019-04-18
    • 2013-07-08
    • 2013-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多