15

When dealing with buisness classes, like the typical Customer and Employee classes, is it better to use getters and setters only or to use properties?

I am translating to Delphi (for self learning) some OO examples from java books, in those examples there is always GetName() and SetName(), properties are not used.

Now, I can see that if I create a component with published properties I have a very good reason for using properties, but in normal classes, which approach is better? Is the code More Readable with getters and setters (that emphasize the fact we are reading/writing a property) or with properties (that at first sight can be confused with parameterless methods)?

4

4 回答 4

40

哇。属性比“它们只是 getter 和 setter 方法的包装器”要多得多。

属性是一种优雅而强大的方式来避免对类字段的受控访问。

访问字段

如前所述,您可以直接访问类字段。这确实非常好,并且使代码更清晰。这也是实现您的类的可行的第一个版本的一种非常好的方法。

TMyClass = class
private
  FValue: String;
public
  property Value: String read FValue write FValue;
end; 

稍后,您可以重新设计您的类以使用方法验证和操作字段访问。公共接口将仍然相同。

TMyClass = class
private
  FValue: String;
  procedure SetValue(AValue: String);
public
  property Value: String read FValue write SetValue;
end; 

procedure TMyClass.SetValue(AValue: String);
begin
  if AValue = '' 
  then FValue := 'No value!'
  else FValue := AValue;
end;

控制访问

属性为您提供了只读/只写字段的简单概述。例如一个只读/不可变类:

TClient = class
private
  FName: String;
  FSite: String;
  FMail: String;
public
  constructor Create(AName, ASite, AMail: String);
  property Name: String read FName;
  property Site: String read FSite;
  property Mail: String read FMail;
end; 

多态性

TClient = class
private
  FName: String;
protected
  function GetName: String; virtual; abstract;
public
  property Name: String read GetName write FName;
end; 

TImportantClient = class(TClient)
protected
  function GetName: String; override;
end; 

TArgumentativeClient = class(TClient)
protected
  function GetName: String; override; 
end; 

function TImportantClient.GetName: String; 
begin
  Result := '+++ ' + FName;
end; 

function TArgumentativeClient.GetName: String; 
begin
  Result := ':-( ' + FName;
end; 

{----- ----- ----- ----- -----}
var
  ClientA,
  ClientB: TClient;
begin
  ClientA := TImportantClient.Create;
  ClientB := TArgumentativeClient.Create;

  ClientA.Name := 'Mr. Nice';
  ClientB.Name := 'Mr. Dumbhead';

  ShowMessage(ClientA.Name);
  ShowMessage(ClientB.Name);
end;
{----- ----- ----- ----- -----}

默认属性

在您的类中,您可以定义一个默认类字段,这意味着您可以直接访问该字段而无需指定属性名称。

A := MyStringList[i]:
MyStringList[i] := B;

{ instead of }

A := MyStringList.Strings[i];
MyStringList.Strings[i] := B;

{ or }

A := MyStringList.GetString(i);
MyStringList.SetString(i, B);

指数

使用Index关键字,Delphi 将一个常量值作为参数传递给 getter/setter 方法。

TMyRect = class
private
  FValues: Array[0..3] of Integer;
  function GetProperty(Index: Integer): Integer;
public
  property Top    : Integer  Index 0  read GetProperty;
  property Left   : Integer  Index 1  read GetProperty;
  property Width  : Integer  Index 2  read GetProperty;
  property Height : Integer  Index 3  read GetProperty;
end;


function TMyRect.GetProperty(Index: Integer): Integer;
begin
  Result := FValues[Index];
end; 

一些资源

还有一些主题需要讨论(实现接口、存储值、RTTI/设计时间属性等),但是这篇文章开始有点长了……

可以在这些网站上阅读更多内容:

于 2010-10-19T13:05:46.887 回答
14

不,Getter 和 setter 只存在于 Java 中,因为它没有属性。它使使用属性的代码更加简洁。然后,如果您需要 getter 或 setter,您可以将其构建到属性中,但您不必在访问代码中乱扔一堆函数调用。

于 2010-10-18T22:36:09.053 回答
10

属性是德尔福的一大优势。我自己已经完成了相当多的 Java 和 Delphi,并且肯定会选择 Properties。实际上,这两种方法最终都会做同样的事情,唯一的区别是属性看起来比 getter/setter 更整洁。

我建议你去房地产,并充分利用它们!

于 2010-10-18T22:35:13.097 回答
4

这真的是品味和使用的问题。

对于类似pascal的程序员来说,读值还是写值是很清楚的,所以我认为如果你不以类似java的方式使用getter和setter,在每一句中写GetXXX或SetXXX,代码的可读性会更好。你的程序。

对我来说,我假设对于大多数 pascal 程序员来说,如果你只输入你正在读/写的属性的名称,代码就会更易读,而且我们都知道会调用 Getter 或 Setter 方法(如果需要) .

此外,我认为 delphi 属性模型的一个巨大好处(和优雅)是您可以直接从字段获取/设置属性值 只需一行代码即可拥有许多 Get/Set 方法,其中值是从字段中分配或读取完全是浪费精力/时间。

于 2010-10-18T22:42:08.217 回答