[英]Ruby refinements with instance_eval
我想對 DSL 進行一些改進。 我可以使用此示例進行改進:
module ArrayExtras
refine Array do
def speak
puts 'array!'
end
end
end
module MyUniverse
using ArrayExtras
class Thing
def initialize
[1].speak
end
end
end
MyUniverse::Thing.new
這會打印出“數組!” 正好。 但是一旦我引入了instance_eval
,就找不到該方法:
module MyUniverse
using ArrayExtras
class DSL
def initialize(&block)
instance_eval(&block)
end
end
end
MyUniverse::DSL.new do
[1].speak
end
我為 [1]:Array (NoMethodError)` 得到了一個undefined method
有沒有辦法在 instance_eval 中進行改進?
細化是詞法范圍的。 您在錯誤的詞法上下文中激活了 Refinement。 您需要在調用精煉方法的地方激活它:
module ArrayExtras
refine Array do
def speak
puts 'array!'
end
end
end
module MyUniverse
class DSL
def initialize(&block)
instance_eval(&block)
end
end
end
using ArrayExtras
MyUniverse::DSL.new do
[1].speak
end
# array!
在某些情況下,您可以通過在綁定上using ArrayExtras
來實現它。
module MyUniverse
using ArrayExtras
class DSL
def initialize(&block)
block.binding.eval("using ArrayExtras")
instance_eval(&block)
end
end
end
MyUniverse::DSL.new do
[1].speak
end
但是,這僅在您不在實例中使用您的類時才有效,僅當binding
是模塊或類上下文時才有效,否則eval
將失敗,因為main.using is permitted only at toplevel
。
如果要細化 ruby 核心BaseObject
,則需要進行如下修改。
module ArrayExtras
refine ::Array do
def speak
puts 'array!'
end
end
end
它將在頂級課程中找到。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.