4

name当我们在下面的代码中定义 getter 和 setter 方法时:

class Animal
    attr_accessor :name
    def initialize(name)
        @name = name
    end
end

内部发生了什么?Ruby 如何获取符号并将其与变量匹配?

4

2 回答 2

6

它使用instance_variable_getand instance_variable_set

更新:正如安德鲁马歇尔所说,不完全是。大多数 ruby​​ 核心方法都是用 C 定义的,但结果基本相同。

可以定义attr_accessor和朋友如下:

def self.attr_accessor(*names)
  names.each do |name|
    define_method(name) do
      instance_variable_get("@#{name}")
    end

    define_method("#{name}=") do |new_value|
      instance_variable_set("@#{name}", new_value)
    end
  end
end

请注意,我在define_method这里也使用了定义访问器方法。

我建议您看一些关于 Ruby 元编程的介绍性文章,例如“不知道 Ruby 中的元编程?” .

于 2012-10-06T15:26:33.100 回答
2

它与变量不匹配,attr_accessor本质上是这样做的(它实际上是用 C 编写的,但我在这里写的大致是 Ruby 翻译):

def attr_accessor(var_name)
  ivar_name = :"@#{var_name}"
  define_method(var_name) do
    instance_variable_get ivar_name
  end
  define_method("#{var_name}=") do |value|
    instance_variable_set ivar_name, value
  end
end

如您所见,它只是使用传递的符号来创建两个方法。它并没有对符号做任何花哨的事情,而且大多只是通过它。另请注意,所有实例变量默认“存在”并设置为nil,因此这永远不会爆炸。

于 2012-10-06T15:28:40.533 回答