作为参数传递时,我可以使对象不可变吗? 所以被调用的方法不能改变它,但被调用者可以吗?
所以我有这样的事情:
Class Car {
Wheel wheel_1;
Axis axis = new Axis(wheel_1);
}
Class Wheel {
int size;
setSize(int size) {}
int getSize() {}
}
现在我建造一辆带轮子的汽车。然后从班级车我想构建一个轴。
为此,我将wheel_1传递给Axis的构造函数。
现在我的问题:我能不能确定Axis的构造函数不会改变wheel_1的大小,但是类车可以改变它。
答案 0 :(得分:5)
使Wheel
类不可变。然后让Car
对象在需要新大小时创建一个新的Wheel
对象。
public final class Wheel {
private final int size;
public Wheel(int size) {
this.size = size;
}
public int getSize() {
return size;
}
}
现在您可以毫无问题地将wheel对象传递给Axis。
public class Car {
private Wheel wheel;
private Axis axis;
public Car(int initialWheelSize) {
wheel = new Wheel(initialWheelSize);
axis = new Axis(wheel);
}
}
答案 1 :(得分:4)
是。通常,这是通过对Wheel
类使用copy-constructor来完成的。
例如:
wheel_1 = new Wheel(wheel);
请记住,Wheel
类需要以支持此类的方式编写。也就是说,它应该提供一个拷贝构造函数。
注意:这并没有使对象不可变。它只是制作了一个副本,不能被你班级以外的任何东西编辑。
如果您从任何其他方法返回Wheel
实例,请务必在出路时防御性地复制它:
Wheel getWheel() {
return new Wheel(wheel_1);
}
最后,值得一提的是,尽可能创建不可变类是一个好主意。那么也许你可以通过实际使Wheel
不可变来避免这个问题?
答案 2 :(得分:3)
将Axis
构造函数传递给wheel_1
。
class Car {
Wheel wheel_1;
Axis axis = new Axis(new Wheel(wheel_1));
}
此外,Wheel
将需要一个构造函数,该构造函数接受另一个Wheel
对象并复制其属性。
答案 3 :(得分:2)
为什么不将参数作为没有setSize()方法的超类发送
Class Car {
Superwheel wheel_1;
Axis axis = new Axis(wheel_1);
}
class Superwheel
{
int size;
int getSize() {}
}
Class Wheel extends Superwheel{
int size;
setSize(int size) {}
int getSize() {}
}
答案 4 :(得分:2)
我想让Wheel实现一个只有访问方法的接口,即: -
示例强>
interface WheelInterface
{
int getSize();
}
class Wheel implements WheelInterface
{
// methods
}
class Axis
{
public Axis(WheelInterface wheel)
{
// Only getSize will be available
}
}
现在,只需传递WheelInterface而不是Wheel,只有访问器方法可用于Axis类的构造函数
<强>优势强>
这样做的好处是不需要复制;您只是向Axis类提供合同,该合同规定它只能获得大小,而不是更改它。
通过按值传递相同的对象引用,您不必调用任何复制构造函数,也不必担心深度和浅层复制语义。我不想在我的方向盘上使用克隆,我认为由于其他答案的评论中提到的原因,感觉有点脏。
在面向对象的模式中,使用界面抽象出你不需要的东西也是良好设计的标志。如果您的车轮上装有雪地轮胎,您的Axis级别可能甚至不需要关心!
<强>缺点强>
正如其他人所提到的,可以将界面强制转换为具体类型(正如其他人提到的那样,假设你知道你要投射的是什么);这被称为向下转换,我不推荐它;如果这是在类似的情况下完成的,它可能不会通过代码审查。
答案 5 :(得分:1)
是的,你可以。如果您将Car和Wheel制作在同一个包中并声明Wheel setter字段受到保护。因此,Axis如果在另一个包中声明,则无法访问Wheel的setter,从而使得Wheel从Axis的角度看是不可变的。
嗯,这个解决方案是基本的开始。当然,你可以根据你想要变化的等级来考虑是否最终制作Wheel,克隆,序列化等等。