为什么调用方法来设置变量比在构造函数中正常设置变量更好?
我当时正在一本 Java 书中做一个项目,并遇到了这个代码示例。该书的作者说,我可以调用类的 setLocation() 方法,而不是直接在构造函数中初始化 X 和 Y。不幸的是,我不再有这本书来具体解释为什么这样做更好。我对 Java 不太有经验,但是直接赋值而不用担心另一个函数调用不是更简单吗?
//Point constructor, normal way of initializing variables
private double x;
private double y;
Point(double initial_x, double initial_y)
{
this.x = initial_x;
this.y = initial_y;
}
//Point constructor, the other way
Point(double initial_x, double initial_y)
{
setLocation(initial_x, initial_y);
}
public void setLocation(double newX, double newY)
{
this.x = newX;
this.y = newY;
}
I was doing a project in a Java book and came across this code example. The author of the book said that instead of initializing X and Y in my constructor directly, I could call the class's setLocation() method instead. Unfortunately I do not have the book anymore for a concrete explanation on why this is better. I'm not too experienced with Java but isn't it just...simpler to assign values directly and not worry about another function call?
//Point constructor, normal way of initializing variables
private double x;
private double y;
Point(double initial_x, double initial_y)
{
this.x = initial_x;
this.y = initial_y;
}
//Point constructor, the other way
Point(double initial_x, double initial_y)
{
setLocation(initial_x, initial_y);
}
public void setLocation(double newX, double newY)
{
this.x = newX;
this.y = newY;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
此资源可能会有所帮助:
http://en.wikipedia.org/wiki/JavaBean
我个人发现使用无参数构造函数可以简化依赖注入。例如,使用 Spring IoC,虽然您当然可以指定构造函数参数,但不必指定要简单得多。
我还发现,出于同样的原因,编写单元测试更简单,即您可以实例化所需的对象,注入测试目的所需的属性,然后进行测试。因此,拥有带有参数的构造函数可能需要您使用您对测试不是特别感兴趣的对象进行设置。
也就是说,提供无参数构造函数与提供带参数的方便构造函数并不相互排斥,即您可以同时拥有两者;只需确保您有一个无参数的可以满足上述用例。
This resource may be of assistance:
http://en.wikipedia.org/wiki/JavaBean
I've personally found that having no-arg constructors simplifies dependency injection. For example with Spring IoC, while you can certainly specify constructor args, its a lot simpler not having to.
Also I've found that writing unit tests is simpler for the same reason i.e. you can just instantiate the object you want, inject the properties required for the purposes of your test and then test. Having a constructor with args may thus require you to set things up with an object that you're not particularly interested in testing.
That said, providing a no-arg constructor is not mutually exclusive to providing convenient constructors with args i.e. you can have both; just ensure that you have a no-arg one to meet the use-cases described above.
如果 x 和 y 是可变的并且具有重要的 setter,那么即使在构造函数中使用 setter 来初始化它们也可以帮助避免代码重复。在这种情况下,您可能希望将 setter 标记为
final
,以防止派生类重写这些方法并导致构造函数出现意外行为。如果 setter 很简单(简单的赋值,没有其他代码),那么就没有太多理由在构造函数中使用 setter。
如果变量是不可变的,那么最好根本没有 setter 并直接在构造函数中初始化它们。
If
x
andy
are mutable and have non-trivial setters, then using the setter to initialize them, even in the constructor, can help avoid duplication of code. In this case, you may wish to mark the setters asfinal
to prevent the possibility of a derived class overriding these methods and causing your constructor to have unexpected behavior.If the setters are trivial (simple assignment with no other code) then there's not much reason to use the setter in the constructor.
If the variables are immutable, it is far better to not have a setter at all and to initialize them directly in the constructor.
如果设置成员涉及一些逻辑,并且您的类是可变的(提供类似于再次调用构造函数的方法),那么使用初始化方法是有意义的。
If there is some logic involved in setting the members, and your class is mutable (providing a method which behaves like calling the constructor a second time) then it makes sense to use an initialization method.
您可以更好地控制它们的设置时间。
You have more control as to when they are set.
因为无论哪个示例,两个实例变量都是私有的,因此在此上下文中
setLocation()
的目的似乎是允许其他类修改Point
对象的坐标,< em>初始化之后。由于构造函数可以有效地完成相同的操作(同样仅针对这个简单的示例),因此构造函数只是为了简单起见而调用该方法。Because both instance vars are private in whichever example, the purpose of
setLocation()
in this context appears to be to allow other classes to modify the coordinates of thePoint
object, after it's been initialized. And since the constructor would have done effectively the same thing (again merely for this simple example), the constructor just calls that method for simplicity's sake.与上面其他人所说的一样,但有一个额外的警告:
如果您出于并发或其他原因需要不可变对象,我可能会看到反对这种做法的争论。如果您正在执行多个线程可能作用于此对象的任何操作,那么 setter 可能会给您带来麻烦。
Same thing as everyone else said above, with an additional caveat:
I could see an argument against this practice if you were in need of immutable objects, for concurrency or other reasons. If you're doing anything where multiple threads might act on this object, the setter is probably going to get you in trouble.
我实际上建议不要在构造函数中调用 setter,因为从构造函数中调用可重写的方法是一个坏主意。此外,getter/setter 的常见论点是逻辑可能会改变,并且您不必更改访问您的属性的每个人。然而,在这种情况下,如果逻辑发生变化,必要的更改仅限于同一个类。
I would actually recommend against calling setters within a constructor, because calling overridable methods from within constructors is a bad idea. Also, the usual argument for getters/setters is that the logic may change, and you won't have to change everyone that accesses your properties. In this case, however, if the logic changes, the necessary changes are limited to the same class.