Delphi 属性与功能或过程之间的差异

Delphi 属性与功能或过程之间的差异,delphi,Delphi,我们可以说: 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

我们可以说:

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...}
?


请向我解释我们在哪里需要使用“财产”,在哪里不需要。Tnx

否。这两个代码不相等

当我们将
TPerson
类作为组件实现时,我们使用
property
,该组件可在Delphi的对象检查器中自定义。例如,看看TButton类。在对象检查器中可以更改的所有内容(
标题
宽度
名称
,等等)都在源代码中用
属性
关键字标记


如果您创建的类将在程序中使用,但不是作为组件使用,则不使用
属性
关键字。

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

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

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

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

这与类的设计有关。从技术上讲,你可以用属性做任何事情,也可以不用属性,但代码不会那么优雅。良好的设计还使类更易于使用,并降低出错的风险

首先,你的比较

TPerson = class
  private
    FName: string;
  public
    property Name: string read FName write FName;
  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;
TPerson=class
私有的
FSweaterColor:字符串;
程序SetWeaterColor(常量值:TColor);
公众的
属性SweaterColor:t颜色读取FSweaterColor写入设置weatercolor;
结束;
...
实施
程序TPerson.SetWeaterColor(常量值:TColor);
开始
如果是FSweaterColor值,则
开始
FSweaterColor:=值;
使无效;//导致控件重新绘制
结束;
结束;
不管怎样,财产有什么意义?基本上,要点是为类创建一个漂亮的接口:对于对其实现细节不感兴趣的人来说,它应该很容易使用。通过使用属性,您可以实现这一目标。事实上,要读取毛衣的当前颜色,只需读取安娜.SweaterColor,要设置它,只需
Anna.SweaterColor:=clRed
。您不知道这是否只是设置了一个变量或导致一个过程运行,您也不在乎。就您而言,
TPerson
对象只有一个名为
SweaterColor
的可读和可设置属性

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

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

更具体地说,如果您使用Delphi IDE进行编程,您将看到
已发布属性
(-y+ies)将显示在对象检查器中,您可以在其中读取/更改它们(如果适用)。如果没有房产,那怎么可能呢

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

所以,毕竟,你需要在一个班级一个班级的基础上决定一个好的班级设计。我猜我过长回答的简短版本与大卫的评论类似:


用你喜欢的,取多的
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;