2015-01-29 6 views
2

У меня есть следующий код:`instance_eval` и прицелы

class A 
    def self.scope 
    yield 
    end 
    def self.method_added method 
    self.instance_eval %{ 
     # do something involving the added method 
    } 
    end 
end 

class B < A 
    scope do 
    def foo 
    end 
    end 
end 

Когда method_added крюк срабатывает, будет код внутри instance_eval перспективе в пределах того же объема, что и метод, который был добавлен? Или он будет работать за его пределами?

В чем заключаются оговорки и вопросы, связанные с этим?

+0

хмм Моя проблема частично решена, все-таки я хотел бы знать, что люди должны сказать, каким-либо образом – Thermatix

ответ

1

Ваш метод scope в основном не работает. Когда вы передаете блок методу, который дает, блок оценивается в области текущей. Обратите внимание:

class A 
    def self.scope 
    yield 
    end 
end 

A.scope { p self } 
# main 

Поскольку ничего не дали к блоку, и ничего не делается с возвращаемым значением yield, любой код запуска в блоке будет иметь тот же эффект, работать вне scope блока.

Это не в случае с instance_eval, однако. Когда instance_eval запускает блок, self в блоке устанавливается на приемник (а не на то, что self находится в области блока). Как это:

class A 
end 

A.instance_eval { p self } 
# A 

Но обратите внимание, что это означает, что self.instance_eval { ... } также фантазии не оп, потому что вы меняете Блока self к тому же self вне блока.

Так что ваш код эквивалентен следующему:

class A 
    def self.method_added method 
    # do something involving the added method 
    end 
end 

class B < A 
    def foo 
    end 
end 
+0

Что означает «не-оп» означает? – Thermatix

+0

Это сокращение от «без операции», что означает инструкцию по программированию, которая ничего не делает. – Max

+0

ах, я вижу, спасибо, теперь все имеет смысл. – Thermatix

1

Давайте узнаем!

class A 
    def self.scope 
    yield 
    end 
    def self.method_added method 
    puts "In method_added, method = #{method}, self = #{self}" 
    instance_eval 'puts "In instance_eval, method = #{method}, self = #{self}"' 
    end 
end 

class B < A 
    scope do 
    puts "In scope's block, self = #{self}" 
    def foo 
    end 
    end 
end 

    # In scope's block, self = B 
    # In method_added, method = foo, self = B 
    # In instance_eval, method = foo, self = B 

Обратите внимание, что вам не нужно self. в self.instance_eval.