문제

호출되는 블록 내부에 호출 된 객체를 잡을 수있는 방법이 있습니까? 예를 들어, 블록이 메소드의 범위에 액세스 할 수있는 방법이 있습니까? 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