2013-04-24 3 views
1

Я хочу назвать instance_eval этого класса:Как передать метод instance_eval?

class A 
    attr_reader :att 
end 

проходя этот метод b:

class B 
    def b(*args) 
    att 
    end 
end 

, но это происходит:

a = A.new 
bb = B.new 
a.instance_eval(&bb.method(:b)) # NameError: undefined local variable or method `att' for #<B:0x007fb39ad0d568> 

Когда b является блок работает, но b как метод не работает. Как я могу заставить его работать?

ответ

0

Этот ответ не использует реальный метод, как просили, но мне не нужно возвращать Proc или изменения A. Это DSL, def_b должно иметь значащее имя для домена, например configure, и его более вероятно определить в модуле или базовом классе.

class B 
    class << self 
    def def_b(&block) 
     (@b_blocks ||= []) << block 
    end 

    def run 
     return if @b_blocks.nil? 
     a = A.new 
     @b_blocks.each { |block| a.instance_eval(&block) } 
    end 
    end 

    def_b do 
    a 
    end 
end 

И он принимает несколько определений. Можно было бы принять только одно определение:

class B 
    class << self 
    def def_b(&block) 
     raise "b defined twice!" unless @b_block.nil? 
     @b_block = block 
    end 

    def run 
     A.new.instance_eval(&@b_block) unless @b_block.nil? 
    end 
    end 

    def_b do 
    a 
    end 
end 
0

Непонятно, какова цель. Вы можете легко обмениваться методами между классами, определив их в модуле и в том числе модуль в каждом классе

module ABCommon 
    def a 
    'a' 
    end 
end 

class A 
    include ABCommon 
end 

Anything = Hash 
class B < Anything 
    include ABCommon 

    def b(*args) 
    a 
    end 

    def run 
    puts b 
    end 
end 
+0

Я хочу иметь состояние в этом классе. – michelpm

+0

См. Редактирование. Думаю, теперь я стал более ясным. – michelpm

Смежные вопросы