假设我有一个名为Truck
的类,其中一个私有成员变量属于类Wheel
。 Wheel
变量getWheel
的getter将返回对它的引用,如下所示:
class Truck{
private Wheel wheel;
Truck(){
wheel=new Wheel();
}
Wheel getWheel(){
return this.wheel;
}
}
class Wheel{
int color;
}
现在,无论谁调用getWheel
都可以随意修改私有成员对象:
class me{
public static void main(String[] args){
Truck ye=new Truck();
Wheel v=ye.getWheel();
v.color=2;
}
}
这会打败封装,不是吗?
对此有什么补救措施?
答案 0 :(得分:8)
通常的做法是:
Wheel
的副本)Wheel
不可变(任何时候你想要改变它,你创建一个新的,用新颜色构建)Wheel
,在Wheel
上返回一个只会暴露getter,不会发生变异操作的不可变接口public
为getter。然后包中的类可以设置Wheel
的颜色,但包外的类不能。 (在这种情况下,我更喜欢#3,以便明确分离,但这也很有效如果你越过可见性边界。)第三个选项是将实例变量(字段)设为非private
通常被视为不良实践的原因之一。
这里的#3更深入,仅仅因为它比#1和#2更复杂,不是因为它必然更好(它不是,设计选择是在上下文中制作。)
一个只读界面,通常是公共的或包私有的,具体取决于您将如何使用所有这些内容:
public interface Wheel {
int getColor();
}
具体类,通常是package-private(如果它是唯一使用过的地方,可以是Truck
中的私有静态嵌套类):
class WheelImplementation implements Wheel {
private int color;
WheelImplementation(int color) {
this.color = color;
}
public int getColor() {
return this.color;
}
void setColor(int color) {
this.color = color;
}
}
Truck
,通常与Wheel
的可见度相同:
public class Truck {
private WheelImplementation wheel;
Truck(){
this.wheel = new WheelImplementation(/*...initial color...*/);
}
Wheel getWheel() {
return this.wheel;
}
}
当然,这可以通过反思来消除,但通常你设计一个API供使用,而不是滥用。 : - )
答案 1 :(得分:2)
您可以为车轮颜色制作私人/包裹设定器。 此外,初始化构造函数中的颜色,这将有助于您这样做。
和其他答案一样,返回Wheel的副本也是一种很好的方法。