Rubyの通過したブロックの呼び出しオブジェクトを参照してください

StackOverflow https://stackoverflow.com/questions/19834086

  •  25-07-2022
  •  | 
  •  

質問

呼び出されているブロック内に呼び出されたオブジェクトを手に入れる方法はありますか。たとえば、ブロックがメソッドの範囲にアクセスする方法はありますか batman またはクラス SuperHeros

class SuperHeros

  attr_accessor :news

  def initialize
    @news = []
  end

  def batman task
    puts "Batman: #{task} - done"
    yield "feed cat"
    @news << task
  end

end

cat_woman = lambda do |task| 
  puts "Cat Woman: #{task} - done" 
  # invoker.news << task
end

robin = lambda do |task| 
  puts "Robin: #{task} - done"
  # invoker.news << task
end


characters = SuperHeros.new
characters.batman("kick Joker's ass", &cat_woman)
characters.batman("break Bane's bones", &robin)
役に立ちましたか?

解決

似たようなものを使用できます 委任されたインスタンス評価 パターン、使用 - たとえば - in サヴォン 宝石:

def batman(task, &block)
  @original_self = eval('self', block.binding)
  puts "Batman: #{task} - done"
  instance_exec('feed cat', &block)
  @news << task
end

private

def method_missing(method, *args, &block)
  if @original_self
    @original_self.send(method, *args, &block)
  else
    super
  end
end

このアプローチでは、ブロック内のメソッド(暗黙のレシーバーを使用)を呼び出すと、 batman 方法、それはのコンテキストで呼ばれます SuperHeros 実例。そのような方法が利用できない場合、通話は(スルー)になります method_missing)オリジナルブロックへ self.

他のヒント

ブロック内で受信機オブジェクトを取得する最も簡単な方法は、オブジェクトをインスタンス変数に割り当てることです。

この例は、Lambdas Cat_womanとRobinがブロックの受信オブジェクトの属性にどのようにアクセスできるかをより明確に示しています。

class SuperHeros
  attr_accessor :news, :name, :current_task

  def initialize(a_name)
    @name = a_name
    @news = []
  end

  def batman(task)
    puts "Inside the method batman of #{name}: #{task} in progress ..."
    @current_task = task
    yield
    @news << task
  end

end

cat_woman = lambda do |extra_task|
  puts "cat_woman even #{extra_task} before doing #{@caller_obj.current_task}"
  puts "Cat Woman: #{@caller_obj.current_task} - done by #{@caller_obj.name}"
  # invoker.news << task
end

robin = lambda do |extra_task|
  puts "robin even #{extra_task} before doing #{@caller_obj.current_task}"
  puts "Robin: #{@caller_obj.current_task} - done by #{@caller_obj.name}"
end


character_1 = SuperHeros.new('batman_1')
(@caller_obj = character_1).batman("kick Joker's ass") { cat_woman['eats some burger'] }

puts

character_2 = SuperHeros.new('batman_2')
(@caller_obj = character_2).batman("break Bane's bones") { robin['drinks some beer'] }

出力は次のとおりです。

Inside the method batman of batman_1: kick Joker's ass in progress ...
cat_woman even eats some burger before doing kick Joker's ass
Cat Woman: kick Joker's ass - done by batman_1

Inside the method batman of batman_2: break Bane's bones in progress ...
robin even drinks some beer before doing break Bane's bones
Robin: break Bane's bones - done by batman_2
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top