[英]instance_eval vs class_eval in module
class Foo
include Module.new { class_eval "def lab; puts 'm' end" }
def lab
super
puts 'c'
end
end
Foo.new.lab #=> m c
================================================== ======================
class Foo
include Module.new { instance_eval "def lab; puts 'm' end" }
def lab
super
puts 'c'
end
end
请注意,我将class_eval更改为instance_eval
Foo.new.lab rescue nil#=> no super class method lab
Foo.lab #=> undefined method lab for Foo class
所以似乎包含模块既没有定义实例方法也没有定义类方法。
有什么解释在这里发生了什么?
此代码在mac上的ruby 1.8.7上进行了测试。
首先,想到什么include
呢。 它使模块的实例方法被包含在包含类的实例方法中。 即,除了您的工作示例使用匿名模块这相当于:
module M1
def lab
puts 'm'
end
end
class Foo
include M1
def lab
super
puts 'c'
end
end
接下来,想一想class_eval
作用。 它在类或模块的上下文中评估给定的代码。 即它就像你重新打开模块并输入传递给class_eval
的代码class_eval
。 所以MyModule = Module.new { class_eval "def lab; puts 'm' end" }
相当于
module MyModule
def lab
puts 'm'
end
end
希望这能解释有效的案例。
当你使用instance_eval
你正在评估接收对象的上下文中的代码(在这种情况下是模块的实例)所以MyMod2 = Module.new { instance_eval "def lab; puts 'm' end" }
相当于
module MyMod2
def MyMod2.lab
puts 'm'
end
end
即它创建了一个模块方法,您可以通过MyMod2.lab
调用MyMod2.lab
并且这些方法不会被include
作为实例方法include
。
请注意 :这个答案从我写给前一个问题的答案中借用了一些解释,这个问题询问了与 Ruby编程语言书中的一个例子有关的instance_eval与class_eval 。 您可能会发现答案也很有用。
包括一个模块只需要实例方法 - 你正在寻找扩展。 幸运的是,为了获得两全其美,你可以简单地做到:
module Something
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def blah
puts "lol"
end
end
end
class Test
include Something
end
IRB:
>> Test.blah
lol
=> nil
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.