الرجوع إلى الكائن الاحتجاج في الكتلة التي تم تمريرها في روبي

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)
هل كانت مفيدة؟

المحلول

يمكنك استخدام شيء مشابه لـ مثيل تقييم مع التفويض نمط ، مستخدم - على سبيل المثال - في سافون جوهرة:

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