Class Delphi类:属性与Get/Set方法
所以我对OO编程有点陌生。Delphi有属性,它是一种比getter/setter更“优雅”的访问类数据的方法(请在此处阅读) 什么时候应该直接使用字段,什么时候应该在属性内部使用getter/setter?我只是在数据需要处理的时候才使用gessing,但我不确定 编辑: 省略只返回字段本身值的setter是否错误Class Delphi类:属性与Get/Set方法,class,delphi,properties,setter,getter,Class,Delphi,Properties,Setter,Getter,所以我对OO编程有点陌生。Delphi有属性,它是一种比getter/setter更“优雅”的访问类数据的方法(请在此处阅读) 什么时候应该直接使用字段,什么时候应该在属性内部使用getter/setter?我只是在数据需要处理的时候才使用gessing,但我不确定 编辑: 省略只返回字段本身值的setter是否错误 property Field :integer read FField write FField; 为什么是房地产? 对于初学者,下面是以下内容的简要总结: 属性(如字段)定
property Field :integer read FField write FField;
为什么是房地产?
对于初学者,下面是以下内容的简要总结:
属性(如字段)定义对象的属性。但是,虽然字段只是一个存储位置,其内容可以检查和更改,但属性将特定操作与读取或修改其数据相关联。属性提供对对象属性访问的控制,并允许计算属性
为什么不仅仅是塞特和盖特?
存储和访问的分离确实可以通过只使用getter和setter来实现,而不使用属性。这是真的,但是您链接到的问题源于语言的差异:Delphi确实有属性,并且那里的答案已经解释了为什么要使用它们。两个最明显的原因是(1)更干净的代码和(2)分配能力。我认为这方面的工作已经相当广泛了
此外,在不使用属性的情况下,始终需要getter和setter,而使用属性则不需要getter和setter。假设是setter实现,但没有getter:属性可以直接读取字段
结业
当您仅声明属性的名称及其类型时,Delphi的类完成默认为读取私有字段和设置私有字段的私有setter。请注意,这只是默认配置,您可以根据需要再次修改它。当您完全指定属性声明时,类完成将符合要求,并根据您的声明添加一个私有字段、一个getter和/或setter
不带getter和setter的属性
省略只返回字段本身值的setter是否错误
当一个属性既没有getter也没有setter,它只读取和写入字段时,您可以得出结论,除了保持一致性之外,没有什么区别。但事实并非如此。字段和属性具有不同的名称,因此可能具有不同的含义。意思是你可以给予。看
何时使用getter或setter?
。。。我只是在数据需要处理的时候才这么说
嗯,这在一定程度上是正确的。操纵是众多原因之一。考虑<代码>价格>代码>属性<代码>字符串< /代码>,其私有字段<代码> f价格< /C> >:
- 限制:当价格需要等于或高于零时
- 委托:当
是另一个字段的一部分时,或者当它超出了此类的责任范围时FPrice
- 验证:当价格在逗号后可能只有两位小数时
- 解释:当价格以千为单位输入,但应以美分为单位存储时
- 影响:当价格对其他领域产生影响时,例如费率或保证金
- 激活:当对价格进行编辑需要立即执行操作时,例如更新GUI
- 换算:当价格以美元输入,但应以日元存储时
- 取消:当价格没有意义时,例如在科学记数法中输入价格时
Price
属性是非常基本的。将其setter或getter留给将来的实现是很有可能的。但是想象一下,如果没有setter或getter,更高级的属性是无法实现的:
- 咨询前需要创建的字段:
function TMyObject.GetBarelyUsed: TRare; begin if FBarelyUsed = nil then FBarelyUsed := TRare.Create(Self); Result := FBarelyUsed; end;
- 可以选择项目,但项目本身不知道该做什么。相反,所有者会这样做。请注意,在本例中完全没有私有字段:
procedure TItem.SetSelected(Value: Boolean); begin if Value <> Selected then begin if Value then Owner.Selection.Add(Self) else Owner.Selection.Remove(Self); end; end;
这样做是不可接受的
TMyClass = class
private
public
Fubar :integer;
end;
你剩下的例子很好。我很高兴收到您这样的代码
TMyClass = class
private
FFu : integer;
public
property Fu :integer read FFu write FFu;
end;
因为我可以自信地把它改成
TMyClass = class
private
FFu : integer;
procedure SetFu(Value : Integer);
function GetBar() : string;
public
property Fu :integer read FFu write SetFu;
property Bar : String read GetBar;
end;
在不破坏现有代码的情况下
我个人不喜欢无所事事的二传手
procedure TMyClass.SetFu(Value : Integer);
begin
FFu := Value;
end;
但事实上,这是无害的
这有用吗
这将是使用二传手的有效理由或激励
procedure TMyClass.SetFu(Value : Integer);
begin
if FFu <> Value then begin
FFu := Value;
if Assigned(FAfterFooChanged) then
FAfterFooChanged(FFu);
end;
end;
过程TMyClass.SetFu(值:整数);
开始
如果是FFu值,则开始
FFu:=数值;
如果已分配(更改),则
fafterfood(FFu);
结束;
结束;
不是这样的“操纵”…除了
@NGLN
答案之外,还有另一个属性getter/setter用例
只有通过实例方法才能通过接口访问类实例。如果在这种情况下必须访问属性,则必须实现getter/setter方法
type
IField = interface
function GetField: integer;
procedure SetField(value: integer);
property Field: integer read GetField write SetField;
end;
TField = class(TInterfacedObject, IField)
protected
FField: integer;
function GetField: integer;
procedure SetField(value: integer);
public
property Field: integer read GetField write SetField;
end;
var
f: IField;
x, n: integer;
...
f := TField.Create;
f.Field := 5;
f.SetField(6);
n := f.Field;
x := f.GetField;
当然,根据您是否只需要对该属性进行读或写访问,您可以在接口声明中省略setter或getter
请记住,通过接口访问实例使所有接口实现的方法都具有公共可见性。这就是为什么在上面的示例中,您可以调用
f.GetField
,尽管它被声明为受保护的(甚至是私有的)。这里有四个问题,这三个问题太多了。即便如此,许多问题实际上是在征求主观意见。我认为你需要缩小关注点。Thx我会想出一个更好的方式来解决它,一个问题本身就是两个问题。使用setter/getter或只是两者的包装器的属性没有真正的区别。getter/setter方法通常是decl
type
IField = interface
function GetField: integer;
procedure SetField(value: integer);
property Field: integer read GetField write SetField;
end;
TField = class(TInterfacedObject, IField)
protected
FField: integer;
function GetField: integer;
procedure SetField(value: integer);
public
property Field: integer read GetField write SetField;
end;
var
f: IField;
x, n: integer;
...
f := TField.Create;
f.Field := 5;
f.SetField(6);
n := f.Field;
x := f.GetField;