4

我们可以说:

type
  TPerson = class
   private
     pName : string;
   public
     property Name : string read pName write pName;
end;

等于:

 type
  TPerson = class
   private
     pName : string;
   public
     procedure SetName(val: string);
     function GetName:String;
end;

//{... implementing SetName And GetName...}

??

请向我解释我们需要在哪里使用“属性”,在哪里不需要。肿瘤坏死因子

4

3 回答 3

13

这都是关于班级设计的。从技术上讲,你可以用属性做的“一切” ,你可以不用它们,但代码不会那么优雅。良好的设计还使类更易于使用,并降低了出错的风险。

首先,你的比较

TPerson = class
  private
    FName: string;
  public
    property Name: string read FName write FName;
  end;

TPerson = class
  private
    FName: string;
  public
    procedure SetName(const Name: string);
    function GetName: string;
  end;

不太公平。事实上,在第一种情况下,当值被设置(或读取)时,你没有机会做某事。因此,更合适的比较是将后一个代码与

TPerson = class
  private
    FName: string;
    procedure SetName(const Name: string);
    function GetName: string;
  public
    property Name: string read GetName write SetName;
  end;

例如,如果您编写一个控件,当您更改属性时,您通常需要使控件无效(基本上是重新绘制),例如TPerson. 例如,

TPerson = class
  private
    FSweaterColor: string;
    procedure SetSweaterColor(const Value: TColor);
  public
    property SweaterColor: TColor read FSweaterColor write SetSweaterColor;
  end;

  ...

  implementation

  procedure TPerson.SetSweaterColor(const Value: TColor);
  begin
    if FSweaterColor <> Value then
    begin
      FSweaterColor := Value;
      Invalidate; // causes a repaint of the control
    end;
  end;

无论如何,属性的意义何在?嗯,基本上,重点是为类创建一个漂亮的接口:对于对其实现细节不感兴趣的人来说,它应该易于使用。通过使用属性,您可以实现此目标。确实,要读取毛衣的当前颜色,您只需读取Anna.SweaterColor,设置它,您只需Anna.SweaterColor := clRed。您不知道这是否只是设置变量或导致过程运行,您不在乎。就您而言,TPerson对象只是具有一个可读且可设置的属性,称为SweaterColor.

您还可以创建只读 (no write) 或只写(no ) 的属性read。但是无论您如何实现属性的readand write(如果有的话),从类用户的角度来看,该属性看起来都是一样的。他不需要记住使用SetSweaterColorGetSweaterColor(事实上,它们是私有的,他无法访问),而只需要使用SweaterColor属性。

这也暗示了使用属性的另一个好处。公共和发布的属性对类的用户可见,而私有成员则不可见(如字段FSweaterColorSetSweaterColor过程)。这很好。因为现在您知道类用户更改一个人的毛衣颜色的唯一方法是使用该SweaterColor属性,这保证会重新绘制控件。如果FSweaterColor变量是公开的,该类的用户可能会设置它并想知道,“为什么当我更改毛衣颜色时没有任何反应?” 当然,您不需要属性来获得此好处:私有FSweaterColor字段和公共字段GetSweaterColorSetSweaterColor可以,但是您需要编写一个GetSweaterColor即使无需处理即可获得颜色。此外,该类的用户需要学习使用两个标识符而不是一个标识符。

更具体地说,如果您使用 Delphi IDE 进行编程,您将看到published property(-y+ies) 将显示在 Object Inspector 中,您可以在其中读取/更改它们(如果适用)。如果没有房产,这怎么可能?

话虽如此,有时即使可以,您也不使用属性。例如,如果您有一个只读“属性”,您可能会选择一个公共GetSomething函数而不是只读属性。毕竟,这将为您节省一些编码。同样,如果您有一个只写属性,您可以使用一个公共SetSomething过程,这也将节省您的代码。最后,如果你有一个读/写属性不需要任何处理(既不需要获取也不需要设置),你可以简单地使用一个公共变量!

因此,毕竟,您需要逐个班级决定班级的良好设计。我想我过长的答案的简短版本类似于大卫的评论:

使用您喜欢的任何一个,哪个更方便。

于 2013-02-16T13:00:58.333 回答
1

属性是一个很好的语法糖。它们相当于一对 getEnabled 和 setEnabled 方法,但大多数程序员(和编程语言)更喜欢属性。例如,代码完成窗口中的条目较少。

此外,它们将“类似变量”的东西(因此数据,对象应该使用)与使用数据的方法分开。

属性不仅限于组件,否则它们非常有用。您可以定义一个带有属性的公共接口,然后实现一些验证逻辑。(不能使用公共字段)但是对于一个简单的属性,您只需要两行代码,而方法是 8 行。

对于对象检查器来说更重要的是发布的关键字,只有发布的属性才会显示在 OI 中。

于 2013-02-16T12:57:23.530 回答
0

不,这两个代码不相等。

我们property在将TPerson类实现为组件时使用,可在 Delphi 的 Object Inspector 中自定义。例如,看一下 TButton 类。您可以在 Object Inspector 中更改的所有内容(CaptionWidthName等)在源代码中都用property关键字标记。

如果您创建一个将在程序中使用但不作为组件使用的类,则不要使用property关键字。

于 2013-02-16T12:07:27.283 回答