Frage

Gibt es eine Möglichkeit, das aufgerufene Objekt in dem aufgerufenen Block zu erreichen? Zum Beispiel gibt es eine Möglichkeit, dass die Blöcke Zugriff auf den Umfang der Methode erhalten batman oder die Klasse 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)
War es hilfreich?

Lösung

Sie können etwas Ähnliches verwenden wie Instanzbewertung mit Delegation Muster, verwendet - zum Beispiel - in Savon Juwel:

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

In diesem Ansatz, wenn Sie die Methode (mit implizitem Empfänger) im Block aufrufen batman Methode, es wird im Kontext von aufgerufen SuperHeros Beispiel. Wenn keine solche Methode verfügbar ist, geht der Anruf (bis method_missing) zum ursprünglichen Block self.

Andere Tipps

Der einfachste Weg, um das Empfängerobjekt in einen Block zu bringen, besteht darin, das Objekt einer Instanzvariablen zuzuweisen.

Dieses Beispiel veranschaulicht deutlicher, wie die Lambdas cat_woman und Robin auf Attribute der Empfängerobjekte von Blöcken zugreifen können:

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'] }

Die Ausgabe wird sein:

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top