【问题标题】:Object assignment in Ruby [closed]Ruby中的对象分配[关闭]
【发布时间】:2012-01-10 20:35:58
【问题描述】:

来自 c++ 背景,我对 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

【问题讨论】:

  • 什么意思,抄袭? q 指向同一个对象 n 确实如此。没有抄袭。如果您更改 n.aq.a 将看到相同的值。
  • 好点,我说错了。问题已更新
  • attr_accessor 定义实例变量/方法,mn 各自看到自己的值。 q 指向n,将充当n

标签: ruby object instance-variables copy-assignment


【解决方案1】:

如果您熟悉 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"

但是,创建 new 对象的操作不会修改所有副本:

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

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

通常分配会用新引用替换旧引用,因此根据经验,= 将替换旧引用。这适用于+=-=||=&amp;&amp;= 等。

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

【解决方案2】:

因为在 ruby​​ 中一切都是对象,所以赋值总是通过引用。

因此,将您的类作为输入,以下将是几个操作的输出:

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

【讨论】:

    【解决方案3】:

    我会改写为:

    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 时,q 仅引用为 n 设置的相同内存位置。对象未被复制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-05
      • 2015-06-02
      • 1970-01-01
      相关资源
      最近更新 更多