2011-12-01 76 views
3

来自C++背景我很好奇Ruby中的对象分配。应当对以下对象分配进行考虑哪些因素(如果有的话):Ruby中的对象分配

class MyClass 

    attr_accessor :a, :b 

    def initialize(a, b) 
    @a = a 
    @b = b 
    end 

    def some_method 
    puts "#{self.a} #{self.b}" 
    end 
end 

m = MyClass.new("first", "last") 
n = MyClass.new("pizza", "hello") 

q = n 
q.some_method 
+2

你是什么意思,复制? 'q'指向同一个对象'n'。没有复制。如果你改变'n.a','q.a'将会看到相同的值。 –

+0

好点,我认为我说错了。问题已经更新 – SundayMonday

+1

'attr_accessor'定义了实例变量/方法,'m'和'n'各自都看到它们自己的值。 'q'指向'n',并将作为'n'。 –

回答

11

如果你熟悉C++,那么你可能要考虑在Ruby中每个变量,实例或以其他方式作为对另一个对象的引用。由于Ruby中的所有内容都是对象,即使是类型为NilClass的nil,在任何情况下都是如此。

要确定您正在引用哪个对象,可以使用object_id方法进行区分。这与在C++中使用&转换为指针类似。

考虑一下:

a = "foo" 
b = a 

a.object_id == b.object_id 
# => true 

由于a是该字符串的引用,ba副本,那么他们实际上是同一个对象的不同引用。

这是因为修改对象的操作会影响所有引用到同样重要的是:创造

a << "bar" 
# => "foobar" 
b 
# => "foobar" 

然而,操作的对象不会修改所有副本:

a += "baz" 
# => "foobarbaz" 
b 
# => "foobar" 

Ruby中的许多方法由!标识,以区分就地版本与新版本版本,但情况并非总是如此,因此您必须熟悉每种方法才能确定。

通常情况下,分配将用新的引用替换旧的引用,因此根据经验法则,=将替换旧的引用。这适用于+=,-=,||=,&&=等。

编辑:根据Phrogz的有关使用ObjectSpace._id2ref(object_id)将对象标识符转换为对象的评论进行更新。

+1

请注意,[你可以基于它的'object_id'来访问一个对象](http://stackoverflow.com/questions/8264732/can-i-or-should-i-find-an-object-by-the-object -id属性合红宝石)。 – Phrogz

3

因为一切都在红宝石的对象,分配总是由参考。

所以,把你的类作为输入,下面将是若干操作的输出:

str = "foo" 
foo = MyClass.new(str, "bar") 
foo.some_method # foo bar 
bar = foo 
bar == foo # true 
bar.some_method # foo bar 
str << "bar" # strings are mutable on ruby, so str is now "foobar" 
foo.some_method # foobar bar 
bar.some_method # foobar bar 
1

我会为这个改写:当您将q = n

class MyClass 

    attr_accessor :a, :b 

    def initialize(a, b) 
    self.a = a 
    self.b = b 
    end 

    def some_method 
    puts "#{a} #{b}" 
    end 
end 

这样,你实际使用类

attr_accessor定义的getter/setter方法,Q只是引用了相同的内存n的位置。该对象不被复制。