C# 中 getter 和 setter 的更好替代方案是什么?

Xan*_*ham 2 c# oop accessor

我读过一些关于在面向对象编程中使用 getter/setter 的内容,并且许多此类资源表明它们应该很少使用。引用那篇文章中的一句话说:

不要询问完成工作所需的信息;询问拥有信息的对象来为您完成这项工作。

虽然原则上这听起来不错,但我不太确定如何最好地实施它。假设我有一个描述汽车的课程。在该类中,假设该类中存储的这辆车的品牌是“丰田”。现在我有一个 GUI 想要显示这是一辆“丰田”。如果没有吸气剂,如何做到这一点?

即使我抽象出“Toyota”存储为字符串并返回一个已写入“Toyota”的 TextBox,这听起来充其量也像是原始属性的包装形式的 getter。我只是认为像 TextBoxes 这样的东西应该只在 GUI 类中,而不是在像我的汽车类这样的辅助类中。

Pet*_*hie 5

那篇文章描述了您应该使用方法而不是属性 getters/setters。基本上,它建议一个方法应该执行修改状态的操作,而不是允许设置器修改状态。例如,我可以有一堂带有“月”和“日”属性的课程。然后我可以有执行此操作的代码:

obj.Day = 28;
obj.Month = Months.February;
obj.Day = 30;
obj.Month = Months.March;
Run Code Online (Sandbox Code Playgroud)

一旦我将一天设置为 30,而月份是 2 月,我就会处于无效状态。

该文章建议类不应允许此类事情,而应提供特定方法来执行特定操作,例如:

obj.ChangeDate(Months.March, 30);
Run Code Online (Sandbox Code Playgroud)

如果日期时间类比由于日期时间而令人困惑,您可以有一个带有纬度/经度坐标的类似示例:

obj.Latitude = 45.4112;
obj.Longitude = -75.6981;
//... 
obj.Latitude = 39.73;
obj.Longitude = -86.27;
Run Code Online (Sandbox Code Playgroud)

当纬度设置为 39.73 时,位置变为纽瓦克附近的地方,而不是渥太华(第一个纬度/经度)或印第安纳波利斯(第二个纬度/经度)。保留纬度/经度的设置会使界面处于开放状态,无法验证其不变量,有些人可能会说不是真正面向对象的。所以,你可能有一个方法:

obj.MoveTo(39.73, -86.27);
Run Code Online (Sandbox Code Playgroud)

OO 意味着封装的状态和行为。虽然有些人可能认为属性“封装”了状态,但他们通常不会。它们将实现与接口分离,以便用作属性后备存储的内容可以更改 - 但很少这样做;因此,这些属性只是提供可用的实现细节,而不是提供公共字段。

有一些概念(例如命令查询分离)建立在这个想法之上,建议接口应该更新状态或查询状态,但不能同时更新状态和查询状态。同时具有 getter 和 setter 的属性提供了一个可以更新状态和查询状态的接口。上述例子MoveToChangeDate“命令”。从概念上讲,您将提供查询状态的其他方式;如果需要的话。

属性的另一个问题是,人们习惯性地添加 getter 和 setter,仅仅因为它是一个属性。获取或设置属性的能力可能不是必需的,并且简单地通过死记硬背添加 getter 和 setter 就可以创建需要测试和维护的接口,而这些测试和维护可能永远不需要。

微妙的?当然; 但他谈论的是面向对象的设计,而不是“正常工作”的代码。