我基本上是一个Java开发人员。 我在红宝石工作了约一年的。 与Java,Ruby是一种纯粹的面向对象的编程语言。 又来了一个疑问。 它是通过按值传递或按引用? Java的工作方式传递的价值:“当传递原语,我看到的价值被复制并传递给方法,但柜面对象,参考被复制并传递给方法的引用包含对象的位置在堆中。在该方法调用中,只有物体的位置被传递,所以不会创建重复的对象。同样的对象被修改“。
但是,当我尝试下面的Ruby代码片段中,我得到了相同的结果,我在Java中有:“这些数字的方法调用期间像一个原始的(在Java等)工作,而阵列工作在Java中一样完美的参考”。 现在,我很困惑。 如果一切红宝石的对象,那么为什么数量对象在方法调用过程中复制?
class A
def meth1(a)
a = a+5
puts "a inside meth1---#{a}"
end
def meth2(array)
array.pop
puts "array inside meth2---#{array}"
end
end
obj1 = A.new
aa=5
obj1.meth1(aa)
puts "aa-----#{aa}"
arr = [3,4,5]
obj1.meth2(arr)
puts "arr---#{arr}"
结果:
一个内部METH1 --- 10
AA ----- 5
阵列内meth2 --- 34
ARR --- 34
红宝石采用传址值,或者更确切地说,一个特殊的情况下,通过按值,其中传递的价值始终是一个指针。 这种特殊的情况下,有时也被称为呼叫通过共享,调用 - 对象共享或调用 - 对象。
这是由Java的使用(对象)相同的惯例,C#(默认情况下为引用类型)的Smalltalk,Python和ECMAScript中/ JavaScript和或多或少的每一个面向对象的语言所创造。
注:所有现有的Ruby实现Symbol
S, Fixnum
S和Float
s的直接价值,而不是与中介指针实际传递。 然而,由于这三个是不可改变的,有之间没有可观察的行为差异传递的价值,在这种情况下,呼叫的对象共享,这样就可以大大简单地处理一切 ,呼叫按对象简化你的心智模型-sharing。 只是解释这三种特殊情况下为你不必担心内部编译器优化。
这里有一个简单的例子,你可以运行以确定红宝石的参数传递约定(或任何其他语言,以后你把它翻译):
def is_ruby_pass_by_value?(foo)
foo.replace('More precisely, it is call-by-object-sharing!')
foo = 'No, Ruby is pass-by-reference.'
return nil
end
bar = 'Yes, of course, Ruby *is* pass-by-value!'
is_ruby_pass_by_value?(bar)
p bar
# 'More precisely, it is call-by-object-sharing!'
这是在两种情况下传递的价值,像Java。 不同的是,在测试中这两个项目都是对象,而在Java中一个本来是一个原始的,其它的对象。 但事情是否是一个原始或对象具有上没有轴承通过按值对通过按引用。 传址值与通按引用有什么所谓的方法可以做到这被传递到它的调用上下文中的变量做。
让我们忽略了这两种语言和对象,只是看看传递的价值与通按引用的实际含义。 我会在一个模糊的B /的Java / C / C ++ / C#/ d语法使用伪代码:
Function Foo(arg) {
arg = 6
}
declare variable a
a = 5
Foo(a)
output a
如果a
通过值传递时,输出为5。如果a
通过引用传递(向变量的引用 a
被给予Foo
),则输出为如图6所示,因为Foo
正在a
经由到变量的引用。
需要注意的是有你的两个测试之间的实质性区别。
在第一个测试,你要指定一个全新的价值a
:
a = a + 5
你不修改的版本a
传递到方法,您使用的值分配一个新值a
。
在你的第二个测试,你只是修改array
:
array.pop
不,例如:
array = ...put something entirely new in `array`...
在您的测试,因为你刚刚修改的对象引用指向,不改变参考的东西,当然你看到了修改。 但是,如果你想真正分配一个新的阵列array
,这种变化不会是在调用上下文中显而易见。
见下文, Object_id
会回答你所有的问题:
class A
def meth1(a)
p a.object_id #=> 11
a = a+5 # you passed a reference to the object `5`,but by `+` you created a new object `10`.
p a.object_id #=> 21
end
def meth2(array)
p array.object_id #=> 6919920
array.pop
p array.object_id #=> 6919920
end
end
obj1 = A.new
aa=5
obj1.meth1(aa)
p aa.object_id #=> 11
arr = [3,4,5]
obj1.meth2(arr)
p arr.object_id #=> 6919920
因此,它真的在你的代码object reference is passed, by value
。 注意+
创建新的对象从而参考是到10
本地进行到它得到了改变的方法。
红宝石,如Java,是通过按值...随着一个问题:被传递的“价值”是(在对象的情况下)的指针引用,所以应在对象值的任何修改的方法中进行,这将是同一个对象的一个在调用上下文上。
现在,你们的例子,你需要知道, Fixnum对象是“立竿见影”的对象只有一个值-在这种情况下,引用不是指针,但对象本身(它仍然是一个对象,用方法等,所以这不是原始象Java)。
在你的榜样,你实际上是重新分配一个新的对象,以你的“一个”指针,这将在所有的情况下,没有在任何地方反映,方法一样:
my_name = "John"
my_name = "Robert"
实际上是分配新指针引用。 由于没有办法改变在Ruby中一个Fixnum的价值,这是不是一个可以正常工作的情况下。
与阵列是个什么情况,你可能期望:你有一个对象,你做对对象状态的修改,并得到修改后的状态恢复。