Ruby修改原始变量

时间:2015-08-11 14:44:39

标签: ruby class reference

在C编程中,我相信他们称之为传递。我想做的就是这个。

class A
  attr_accessor :foo
  def initialize
    @foo = 'foo'
  end
  def get_b
    _b = Object.new
    _b.extend B
    _b.foo = @foo
  end
  module B
    attr_accessor :foo
    def change_foo
      @foo = 'bar'
    end
  end
end

a = A.new
puts a.foo # 'foo'
b = a.get_b
puts b.foo # 'foo'
b.change_foo
puts b.foo # 'bar'
puts a.foo # This should also be 'bar' but is instead still 'foo'

b.change_foo之后,我希望修改a.foo的值。有没有办法将@foo的引用从class A传递给module B而不是值?

2 个答案:

答案 0 :(得分:3)

通过这个字符串的具体示例,您可以使其工作。

module B
  attr_accessor :foo
  def change_foo
    # @foo = 'bar' # this won't work
    foo.replace('bar')
  end
end

当你执行@foo = 'bar'时,你完全打破了B的foo和A的foo之间的任何联系。它们现在是两个独立的对象。

上面的代码所做的是,而不是创建另一个对象,使用对象的引用来调用它的方法(这将改变它的状态)。与其他可变对象(数组,哈希,自定义类的实例)一样可以正常工作。但不是像整数这样的不可变原语。

  

有没有办法将@foo的引用从A类传递给模块B而不是值?

参考(或“指针”,在C语言中) 实际上是在这里传递的。然后你覆盖它。

答案 1 :(得分:1)

对象在Ruby中作为引用传递,但不是指向变量的指针。这意味着,虽然您可以修改任何对象,但如果更改变量的引用,则此更改将仅在当前范围内发生。我建议您实际更改架构并使用更多面向对象的技术,而不是试图依赖像这样的容易出错的语言功能。例如,您可以使用合成和委派来实现您尝试完成的任务:

class A
  attr_accessor :foo
  def initialize
    @foo = 'foo'
  end

  def get_b
    _b = Object.new
    _b.extend B
    _b.a = self
  end

  module B
    attr_accessor :a

    def foo
      a.foo
    end

    def foo=(value)
      a.foo = value
    end

    def change_foo
      a.foo = 'bar'
    end
  end
end

我不确切地知道你的目的,但我可能不会像这样在工厂方法中动态扩展模块。我更喜欢创建目的明确的类,而不依赖于上下文。