修改setter参数是否正常?让我们假设我们有setString方法。我们真的想保留一个修剪过的字符串形式。所以带尾随空格的字符串无效,但我们不想抛出异常。
什么是最好的解决方案?修剪设置器中的值,例如
public void setString(String string) {
this.string = string.trim();
}
或者在调用者中修剪它(不止一次),例如
object.setString(string.trim());
或者别的什么?
答案 0 :(得分:10)
是。毕竟,setter是为这类东西而设计的!控制和清理写入字段的值;)
答案 1 :(得分:1)
共。这是一个例子:假设您有一个包含不同类型测量单位的工程程序。您将内部值保留在一个测量系统中,但是您可以从setter中的所有其他值转换,然后在getter中转换回来,例如:
public double UserTemperature
{
get
{
return Units.Instance.ConvertFromSystem(UnitType.Temperature, temperature);
}
set
{
double v = Units.Instance.ConvertToSystem(UnitType.Temperature, value);
if (temperature != v)
{
temperature = v;
Changed("SystemTemperature");
Changed("UserTemperature");
}
}
}
答案 2 :(得分:0)
是的,当然。在应用任何方法(例如trim())之前,请注意检查NULL。
答案 3 :(得分:0)
有两个学校:一个说可以在setter(学校风格)中检查param,第二个说bean不应该包含任何逻辑和数据(企业风格)。
我更相信第二个。您多久查看一次bean的实现?应该getUser抛出任何异常还是只返回null?
当你在你的setter和getter中放入逻辑时,你会更难理解发生了什么,因为许多人永远不会看到它的实现。如果您不同意,我建议您在使用之前先查看每个setter和getter实现,以检查它是否只是一个bean。
答案 4 :(得分:0)
乍一看似乎违反了principle of least astonishment。如果我是你班级的用户,我会期待一个二传手完全按照我所说的去做。我会在setter中抛出一个异常来强制用户修剪输入。
另一个(更好的?)替代方法是将方法的名称更改为trimAndSetString。这样,修改输入就不足为奇了。
答案 5 :(得分:0)
如果我错了,请纠正我,但对我而言,设定者应该持有这种逻辑是合乎逻辑的。 如果setter只是在不检查内部var的情况下为内部var赋值,那么为什么不公开var本身?
答案 6 :(得分:0)
这正是您使用setter而不是将对象字段暴露给整个世界的原因。
考虑一个包含预期在0到359之间的整数角度的类。
如果公开该字段,调用函数可以将其设置为他们想要的任何内容,这将破坏API指定的合同。它也可能会在轨道上的某个地方破坏你的功能,因为你的代码被编写为假定该变量的某个范围。
使用setter,你可以做很多事情。一种是引发异常以指示传递了无效值,但在我看来这是不正确的(对于这种情况)。如果将输入值修改为0到359之间的值,则可能会更有用,例如:
actualVal = passedValue % 360;
只要在您的界面(API)中指定了它,它就完全有效。事实上,即使你没有指定它,你仍然可以自由地做任何你想做的事情,因为调用者违反了合同(通过传递超出范围的值)。我倾向于遵循“尽快消毒你的意见”的规则。
在您的特定情况下,只要您指定字符串以修剪格式存储,调用者就没有理由抱怨(您已经声明这样的字符串无效)。在setter中而不是在调用setter的每一段代码中,在代码大小(而不是速度)方面做得更好。它还保证字符串按照您的预期存储 - 不能保证调用者不会意外(或故意)存储未修剪的字符串。
答案 7 :(得分:0)
是。面向对象设计的一个特点是调用者可以将您的类视为黑盒子。你在里面做的是你自己的事业,只要界面的行为是记录和逻辑的。
答案 8 :(得分:0)
虽然不同的人有不同的哲学,但我建议属性设定者仅适用于他们将对象的状态设置为与指示值匹配的情况,并且可能通知任何关心变化的人,但不会否则会影响对象的状态(如果属性是根据与属性设置器关联的状态定义的,则属性设置器更改只读属性的值是完全正确的;例如,控件的只读Right
属性可以根据其Bounds
来定义。如果属性设置者无法执行指示的操作,则应该抛出异常。
如果有人希望允许客户端以某种方式修改对象的状态而不满足上述描述,则应该使用方法而不是属性。如果有人调用Foo.SetAngle(500)
,则可以合理地预期该方法将在设置角度时使用指示的参数,但Angle
属性可能不会以与设置相同的形式返回角度(例如,可能会返回140)。另一方面,如果Angle
是读写属性,则可能会禁止写入值500,否则会导致值读回500.如果想要拥有对象存储在0到359范围内的一个角度,该对象也可以有一个名为BaseAngle
的只读属性,该属性将始终以该形式返回一个角度。