我昨天编写了自己的LinkedList实现。我正在做这样的事情:
public class Node
{
Node next;
int value;
public Node()
{
next = null
value = 0;
}
}
然后在使用Node
我正在做node.next
和node.value
时。然后我意识到 - 等等,我到底在做什么?这些实例变量应该是private
然后我应该使用getters()和setters()来访问getNext()
和setValue()
。
这让我想知道,什么时候其他而不是private
实例变量?
答案 0 :(得分:4)
从技术上讲,你提出了两个问题:标题问题,“什么时候有一个公共实例字段”,以及你的最后一句,“什么时候有一个非私有实例字段。” / p>
什么时候有一个公共实例字段?几乎每个人都知道答案几乎从来没有。我认为它们偶尔适用于非常小的值类,其行为类似于简单的C结构。一个很好的例子是java.awt.Point和java.awt.Dimension。
这些实际上是特别好的例子,因为它们最终演变为使用访问器方法,尽管它们很简单,这是一个很好的教训:即使是看起来如此简单以至于公共字段看起来可以接受的类也有可能成为某种东西这需要封装。 (Point and Dimension继续保留这些公共字段以实现向后兼容。)
何时适合拥有非私有实例字段?大多数人没有利用这样的事实:没有访问修饰符的字段和方法(和类)是包私有的,但是包私有字段在很多情况下都很有用。由于它们只能通过相同的包访问,因此通常情况下它是您的代码,您可以相信自己不会做会损坏对象的“坏事”。我会说,包私有字段的合法用途比公共字段要多得多。
也就是说,Point / Dimension规则仍然适用:有很多次我认为我可以使用包私有字段,但后来发现我需要通过get-和set-methods进行封装。
保护字段的使用可能远远超出应有的范围。在我看来,让子类直接修改状态而不是通过方法很少有很大的收获。
答案 1 :(得分:1)
如果您实际上不需要来保护它们免受任意访问或更改(例如,当允许值采用任何整数或简单的空映射时)将“检索到的值”改为“对象中的值”),将吸气剂或固定器包裹起来是没有意义的。
如果是这种情况,代码有时看起来更自然,使用:
object.value = 42;
而不是:
object.setValue (42);
(虽然与我的眼睛的区别很小)。
话虽如此,我仍然更喜欢getter和setter,因为如果在将来的某个时候你需要将逻辑合并到成员中,将公共成员更改为该成员的getter / setter将破坏该类的API,包括对使用它的所有客户端的更改。
这可以包括(但绝不限于):
答案 2 :(得分:1)
经典的例子是一个代表二维数学点的类。
public class Point {
public float x;
public float y;
public Point( float x, float y ) {
x = x;
y = y;
}
public void scale( float c ) {
x *= c;
y *= c;
}
public void rotate( float angle, Point center ) {
// whatever this logic is; I forget
}
}
Point
实际上只是两个浮动的容器,可以任意改变。您不会直接访问x
和y
,而不是强迫用户通过getter和setter来伤害任何事情。同时,缩放和旋转等一些操作很常见,因此值得创建一个类,该类提供了对坐标进行必要数学运算的方法。
请原谅(或更好,更正)代码中的任何语法或其他错误。我好像没有写过任何Java。
答案 3 :(得分:0)
您必须查看Java中的访问说明符。有关快速参考:http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html