那篇文章描述了您应该使用方法而不是属性获取器/设置器。基本上,它建议一个方法应该执行一个操作来修改状态,而不是允许设置器修改状态。例如,我可以有一个具有月和日属性的类。然后我可以有这样的代码:
obj.Day = 28;
obj.Month = Months.February;
obj.Day = 30;
obj.Month = Months.March;
一旦我将一天设置为 30 而月份是二月,我就会处于无效状态。
文章建议一个类不应该允许这种类型的事情,而是提供特定的方法来执行特定的操作,例如:
obj.ChangeDate(Months.March, 30);
如果日期时间类比由于 DateTime 而令人困惑,您可以使用 lat/long 坐标的类似示例:
obj.Latitude = 45.4112;
obj.Longitude = -75.6981;
//...
obj.Latitude = 39.73;
obj.Longitude = -86.27;
当纬度设置为 39.73 时,该位置将变为靠近纽瓦克而不是渥太华(第一个纬度/经度)或印第安纳波利斯(第二个纬度/经度)的地方。保留纬度/经度设置会使界面开放,无法验证其不变量,有些人可能会说不是真正面向对象的。因此,您可能有一个方法:
obj.MoveTo(39.73, -86.27);
OO 意味着封装状态和行为。虽然有些人可能认为属性“封装”了状态,但它们通常不会。它们将实现与接口分离,以便用作属性后备存储的内容可以更改——但是,它很少这样做;因此,这些属性只是提供与提供公共字段不同的实现细节。
有像命令查询分离这样的概念建立在这个想法上,建议接口应该更新状态或查询状态,但不能同时更新。同时具有 getter 和 setter 的属性提供了更新状态和查询状态的接口。上面的例子MoveTo
和ChangeDate
将是“命令”。从概念上讲,您将提供其他查询状态的方法;如果需要的话。
属性的另一个问题是人们习惯性地添加 getter 和 setter 仅仅是因为它是一个属性。获取或设置属性的能力可能不是必需的,只需通过死记硬背的创建和接口添加 getter 和 setter,这可能永远不需要测试和维护。
微妙的?当然; 但他说的是面向对象的设计,而不是“正常工作”的代码。