【发布时间】:2017-06-18 13:14:11
【问题描述】:
我有一个简单的测试:
def swap(a, b)
c = a
a = b
b = c
end
a = 3
b = 4
swap(a, b)
print a # 3. not change value
我知道此示例不适用于 Java 或 C# 等某些语言,因为这些变量是原语。但是在 Ruby 中,如果一切都是对象,我认为上面的示例应该可以工作。请给我解释一下。
我认为问题在于 FixNum 是不可变的。我有使用 Java 的概念验证代码来制作一个不可变的整数类:
static class CustomInteger {
Integer value;
public CustomInteger(int i) {
this.value = i;
}
public void changeValue(int i) {
this.value = i;
}
public int getValue() {
return value;
}
public CustomInteger setValueImmutable(int i) {
return new CustomInteger(i);
}
}
public static void swap(CustomInteger a, CustomInteger b) {
int c = a.getValue();
a.changeValue(b.getValue());
b.changeValue(c);
}
public static void main(String[] args) {
CustomInteger i1 = new CustomInteger(3);
CustomInteger i2 = new CustomInteger(4);
swap(i1, i2);
System.out.println(i1.getValue());
}
public static void notWorkSwap(Integer a, Integer b) {
int temp_a = a;
int temp_b = b;
a = temp_b;
b = temp_a;
}
【问题讨论】:
-
Fixnum对象是不可变的。见this answer。 -
@TrầnKimDự,我 1000% 确定这个确切的代码不会在 c/c++/c#/java/whatever 中交换它们。如果您传递指针并更改这些指针的地址 - 是的。但不是这样的常规任务。
-
@TrầnKimDự,这不是原因。注意你是如何使用
a.changeValue(b.getValue())而不是a = b或a = b.getValue()。赋值 (=) 只是改变了局部变量所指的内容。前一个值或新值是否可变并不重要。 -
@TrầnKimDự,装箱/拆箱是对应类的基元和对象之间的神奇转换。这与它无关。调用
changeValue不是“为对象赋值”,它调用了一个为实例变量赋值的方法。它仍在调用方法,而不是赋值。 -
@TrầnKimDự,它不起作用,因为您假设取消装箱会更改值是不正确的。它不会改变任何东西,它只是为您提供底层的原始值。装箱也不会改变任何东西,它会创建一个包装该值的新对象。在右侧完成任何包装/展开之后,它仍然像正常分配一样简单地分配。