[英]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.