繁体   English   中英

在C#中,有什么更好的替代方法来使用getter和setter?

[英]What are better alternatives to getters and setters in C#?

我看过一些关于面向对象编程和很多资源,如使用getter / setter方法的这个建议,他们应该是非常不经常使用。 该文章的引言说:

不要要求您进行工作所需的信息; 询问具有该信息的对象为您完成工作。

虽然这在原则上听起来不错,但我不确定如何最好地实现这一点。 说我有一堂课描述一辆汽车。 在该类别中,可以说该类别中存储的这款汽车的品牌是“丰田”。 现在,我有一个GUI,它想要显示这是“丰田”。 没有吸气剂怎么办?

即使我抽象出“ Toyota”作为字符串存储并返回一个文本框,其中已写有“ Toyota”,但这听起来充其量不过是原始属性的包装形式的获取器。 我只是认为诸如TextBoxes之类的东西应该只在GUI的类中,而不应该在我的car类之类的帮助器类中。

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

obj.Day = 28;
obj.Month = Months.February;
obj.Day = 30;
obj.Month = Months.March;

一旦我将日期设置为30,而月份为2月,则状态为无效。

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

obj.ChangeDate(Months.March, 30);

如果由于DateTime而使日期时间类比令人困惑,则可以使用经纬度坐标类似的示例:

obj.Latitude = 45.4112;
obj.Longitude = -75.6981;
//... 
obj.Latitude = 39.73;
obj.Longitude = -86.27;

当“纬度”设置为39.73时,该位置将成为Newark附近的位置,而不是渥太华(第一纬度/经度)或印第安纳波利斯(第二纬度/经度)。 保留纬度/经度的设置会使接口处于无法验证其不变性的开放状态,并且有些人可能说不是真正面向对象的。 因此,您可能有一个方法代替:

obj.MoveTo(39.73, -86.27);

OO意味着封装状态和行为。 尽管某些属性可能会“封装”状态,但通常不会。 它们将实现与接口分离开来,以便可以更改用作属性的后备存储的东西,但是很少这样做。 因此,这些属性只是在提供实现细节方面与提供公共字段不同。

有一些类似“命令查询分离”的概念都建立在该思想的基础上,建议接口应该更新状态或查询状态,但不能同时更新状态或查询状态。 带有getter和setter的属性提供了同时更新状态和查询状态的接口。 上面的示例MoveToChangeDate将是“命令”。 从概念上讲,您将提供其他查询状态的方法。 如果需要的话。

属性的另一个问题之一是,人们仅仅因为它是一个属性就习惯性地同时添加了吸气剂和吸气剂。 可能不需要获得或设置属性的能力,只需简单地通过死记创建和接口同时添加getter和setter即可,而不需要进行测试和维护。

微妙? 当然; 但是他在谈论的是面向对象的设计,而不是“有效”的代码。

您将忽略“完成工作”。 如果您要完成的工作是汽车的品牌,则返回该品牌的吸气剂即可完成工作。

文章的意思是,如果您希望对类数据进行处理,请将其放入类中。 不要从类中提取数据,对其进行处理,然后将其返回给类:

var c = new Car();
c.Odometer += 10;  // bad
c.DriveMiles(10);  // good

我也质疑该文章对C#的适用性。 它声称:

getter和setter方法(也称为访问器)很危险,其原因与公共字段很危险:它们提供了对实现细节的外部访问。

在C#中,这是错误的,C#访问器可以接受任意类,它们不“提供对实现细节的外部访问”。

getter和setter并不是邪恶的,只是不应该为每个属性自动生成它们。 就您的示例而言,一个Car类可能应该具有一个返回字符串的getBrand方法,但是可能不需要此属性的设置方法。 Car中返回品牌名称的TextBox的方法比返回字符串的简单getter方法更糟糕,因为它不是很通用。

我现在可以看到Peter Ritchie的答案:changeDate的好例子。 Date类应该提供类似的方法,而不是提供日和月的getter,并且需要用户代码自行计算日历中的第二天。

基本上,他的意思是说您有一个具有十个属性的类,并且您想将其转储到一行csv中。 将Tocsv方法添加到类中以返回其中包含一堆csvs的字符串。 不要编写通过属性访问它并构建csv字符串的其他类,因为它们必须紧密耦合。

不知道为什么要选出访问器,问题在于它们与获取和设置离散方法完全相同,或者更糟糕的是成员变量。

显然有限制,您必须有充分的理由更换

SomeLabel.Text = SomeInstance.StringValue;

SomeInstance.MakeStringValueALabel(SomeLabel);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM