【问题标题】:usage of property vs getters/setters in business classes在业务类中使用属​​性与 getter/setter
【发布时间】:2011-04-27 04:56:05
【问题描述】:

在处理业务类时,例如典型的 Customer 和 Employee 类,是只使用 getter 和 setter 还是使用属性更好?

我正在将java书籍中的一些OO示例翻译成Delphi(用于自学),在这些示例中总是有GetName()和SetName(),没有使用属性。

现在,我可以看到,如果我创建一个具有已发布属性的组件,我有充分的理由使用属性,但在普通类中,哪种方法更好?使用 getter 和 setter(强调我们正在读取/写入属性的事实)或使用属性(乍一看可能与无参数方法混淆),代码是否更具可读性?

【问题讨论】:

  • “属性”(在 Delphi/C# 意义上) getter-and-setter。它们实际上只是集成到语言/运行时中。 Java 没有这样的直接对应物。
  • @pst:Delphi 中的属性不一定是 getter 和 setter。它们可以是,或者如果您不需要任何额外的处理,它们可以直接访问基础字段。
  • 明智的是,要记住直接访问类字段将限制某些 OO 技术的使用。例如。接口中的属性必须通过方法实现,多态性(虚/抽象属性)需要虚getter/setter方法。

标签: delphi properties getter-setter coding-style


【解决方案1】:

哇。属性不仅仅是“它们只是 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/设计时属性等),但是这篇文章开始有点长了...

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

【讨论】:

  • 属性还有很多 - 当然。
【解决方案2】:

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

【讨论】:

  • 所有答案都是正确的,反正我选一个来告诉问题已经回答了。
  • 一个问题:在一个类中,我可以读/写私有字段或公共属性。是否有始终在课堂内使用该字段的指南?因为如果没有规则,有时人们会写入字段,有时会写入属性,这样属性就变成了一个令人困惑的工具。可以在同一个类中看到 FName := 'Test' 和 Name := 'Test'。
  • 这取决于您是否还希望触发 Name 属性的任何设置器。 setter 可能会触发您当时可能或不想启动的事件等。
  • 正如其他人已经说过的,属性是一种远远超出语法糖的宝贵资源,因为它提供简洁、清晰、优雅和受控访问。 但是有一个警告。仔细观察属性的任何 getter 或 setter 都没有任何副作用。这种隐藏的语义可能会让你的类真的很难使用。与普通的 getter setter 函数相比,属性中的附带损害更难理解和最终更正。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2015-10-15
      • 1970-01-01
      • 2020-07-18
      • 1970-01-01
      • 1970-01-01
      • 2021-10-22
      • 2016-05-03
      • 2011-06-13
      • 1970-01-01
      相关资源
      最近更新 更多