簡體   English   中英

使用 instance_eval 進行 Ruby 改進

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM