1

我正在阅读Metaprogramming Ruby,只是想澄清一下以下释义代码:

class MyClazz
  def self.my_class_method(name)
    define_method(name) {
      # do stuff
    }
  end

  my_class_method :foo
  my_class_method :bar
end

# The code above generates instance methods:

# def foo
#   do stuff
# end

# def bar
#   do stuff
# end

Q1 我的第一个问题是关于文件末尾的两个方法调用:my_class_method :foomy_class_method :bar. 我是否认为在实例化 MyClazz 对象时它们都会自动调用?

Q2当 Ruby 生成这些方法 (def foodef bar) 时,它会将它们放在MyClazz 的eigenclass 中,即使它们是实例方法。那么这是否意味着 Ruby 在需要时会针对类和实例方法查找 eigenclass?

我只是想在我深入本书之前澄清这一点。

4

2 回答 2

3

答案 1:( 简短)MyClass当 ruby​​ 实例化实例(类型)时调用它们Class

(long)当 Ruby 解释器看到一个类定义 ( class MyClazz) 时,它会实例化这个类的一个实例并评估类定义中的所有代码。

在您的情况下MyClazz,是一个包含对 class 对象的引用的常量Class。当 Ruby 初始化它时,它会在类定义中执行代码 - 定义此实例的单例方法my_class_method并在此实例的上下文中Class执行my_class_method两次方法Class

答案2:( 简短) Module#define_method私有方法将方法添加到Class实例的方法表中(方法表保存类的实例方法)。它不影响 istance 对象/类对象的 eigenclass。

(long)当你在对象上调用实例方法时,Ruby 首先在这个对象的 eigenclass 中查找这个方法,然后在 eigenclass 的超类中查找这个方法(它将是该Class对象类的一个对象)。但它不会查看MyClazz 对象的特征类。

例子:

obj = MyClazz.new
obj.foo # => ok

obj.foo将在对象foo的 eigenclass 中查找方法定义obj,然后将查找MyClass(类的实例Class)的实例方法,然后在MyClass对象的超类中(在您的情况下是Object类)等。

obj = MyClass.new
MyClass.my_class_method :baz
obj.baz # => ok

MyClass.my_class_method将在对象的特征类中查找my_class_method方法定义MyClass(旁注:类的特征类有时称为元类),它会在这里找到它并将baz实例方法添加到类MyClass中。

于 2012-03-24T09:52:11.587 回答
2

A1:是的,这些方法是在实例化时创建的。

A2:Russ Olsen 在他的《Eloquent Ruby》一书中很好地解释了这一点。eigenclass(或单例类)“位于每个对象及其常规类之间”。因此,当 Ruby 在实例方法中找不到它正在寻找的方法时,它将开始沿着继承树向上移动。下一站是特征类,然后是类本身。

Olsen 还对所有 Class 方法实际上是新类和 Class 对象之间的单例方法进行了有趣的讨论。

于 2012-03-24T04:59:45.970 回答