我正在阅读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 :foo
和my_class_method :bar
。我是否认为在实例化MyClazz对象时会自动调用它们?
Q2 当Ruby生成这些方法(def foo
和def bar
)时,它会将它们放在 MyClazz的本征类中,即使它们是实例方法。那么这是否意味着Ruby在需要时会查找类和实例方法的本征类?
我只是想在我向书中移动太远之前将其清除。
答案 0 :(得分:3)
答案1: (简短)当ruby实例化MyClass
实例(类型为Class
)时,会调用它们。
(long)当Ruby解释器看到类定义(class MyClazz
)时,它实例化该类的实例并评估类定义中的所有代码。
在您的情况下,MyClazz
是一个常量,它包含对类Class
的对象的引用。当Ruby初始化它时,它在类定义中执行代码 - 定义此my_class_method
实例的单例方法Class
,并在此my_class_method
实例的上下文中执行两次方法Class
。
答案2: (短) Module#define_method
私有方法将方法添加到Class
实例的方法表中(方法表保存实例方法)班级)。它不影响istance对象/类对象的本征类。
(long)当你在对象上调用实例方法时,Ruby首先在这个对象的本征类中查找此方法,然后在eigenclass的超类中查找(它将是Class
对象类的对象)。但它不会查看MyClazz
的本征类
对象
示例:强>
obj = MyClazz.new
obj.foo # => ok
obj.foo
将在foo
对象的本征类中查找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
。
答案 1 :(得分:2)
A1:是的,这些方法是在实例化时创建的。
A2:Russ Olsen在他的“Eloquent Ruby”一书中做了很好的解释。特征类(或单例类)“位于每个对象及其常规类之间”。因此,当Ruby没有找到它在实例方法中寻找的方法时,它将开始沿着继承树向上移动。下一站是本征类,然后是类本身。Olsen还提供了一个有趣的讨论,关于所有Class方法实际上是新类和Class对象之间的单例方法。