商务类中属性的使用与 getter/setter 的比较

发布于 2024-09-28 04:43:35 字数 281 浏览 1 评论 0原文

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

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

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

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)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

抚你发端 2024-10-05 04:43:35

哇。属性的含义远不止“它们只是 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

使用 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/设计时属性等),但是这篇文章开始变得有点长......

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

Wow. There is sooo much more to properties than "they'r just wrappers for the getter and setter methods".

Properties are an elegant, yet powerful, way to provoide controlled access to the class fields.

Accessing fields

As already stated, you can access the class fields directly. This is very nice indeed and makes the code clearer. It is also a very nice way to implement a workable first version of your class.

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

Later on, you can redesign your class to validate and manipulate the field access using methods. The public interface will is still the same.

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;

Controlling access

Properties gives you an easy overview of readonly/writeonly fields. E.g. a readonly/immutable class:

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; 

Polymorphism

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;
{----- ----- ----- ----- -----}

Default properties

In your class, you can define a default class fields which means that you can access the field directly without specifying the property name.

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

With the Index keyword, Delphi will pass a constant value as an argument to the getter/setter methods.

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; 

Some resources

There are still some topics to cover (implementing interfaces, stored values, RTTI/design time properties etc), but this post started to get a bit long...

More can be read at these sites:

帅气尐潴 2024-10-05 04:43:35

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

No. Getters and setters are only there in Java because it doesn't have properties. It makes for much cleaner code to use properties. And then if you need a getter or a setter, you can build it into the property, but you don't have to litter the accessing code with a bunch of function calls.

冧九 2024-10-05 04:43:35

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

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

Properties are a great advantage of Delphi. I have done quite a bit of Java and Delphi myself and definitely would go for Properties. Practically both approaches will eventually do the same thing, with the only difference that properties look MUCH neater than getters/setters.

I suggest you go for properties, and take full advantage of them!

转身以后 2024-10-05 04:43:35

这确实是一个品味和用途的问题。

对于像 pascal 这样的程序员来说,如果你正在读取或写入一个值,这是非常清楚的,所以我认为如果你不以类似 java 的方式使用 getter 和 setter,即在每一个句子中编写 GetXXX 或 SetXXX,那么代码的可读性会更高你的程序。

对于我来说,我假设对于大多数 pascal 程序员来说,如果您只输入正在读取/写入的属性的名称,则代码更具可读性,并且我们都知道将调用 Getter 或 Setter 方法(如果需要) 。

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

It really is a matter of taste and use.

For pascal like programmers, it's very clear if you're reading or writing a value, so I think the code is more readable if you do not use getters and setters in the java-like way where you write GetXXX or SetXXX in every sentence of your program.

For me, and I assume for the majority of pascal programmers, the code is more readable if you just put the name of the property you're reading/writing, and we all know a Getter or Setter method will be called (if necessary).

Also, I think it is a huge benefit (and elegance) from the delphi property model that you can get/set the property value directly from a field To have a lot of Get/Set methods with just a line of code where the value is assigned or read from a field is a total waste of effort/time.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文