2009-05-22 5 views
2

Имея некоторые проблемы с расширением экземпляра объекта с помощью модуля, особенно когда я определяю обратный вызов extend_object в классе Module. Я понимаю, что когда вы делаете что-то вроде:Расширение объекта ruby; Обратный вызов extend_object предотвращает расширение методов экземпляра

(s = String.new) .extend SomeModule

SomeModule extend_object обратного вызова вызывается. Это похоже на случай, но когда я включаю обратный вызов, ни один из методов экземпляра, определенных в SomeModule, не отображается в объекте. Часть кода должна лучше объяснить:

module M1 
    def self.extend_object(o) 
    end 

    def test_method 
    true 
    end 
end 

module M2 
    def test_method 
    true 
    end 
end 

(x = String.new).extend(M1) 
(y = String.new).extend(M2) 

Затем

x.methods.include?("test_method") 
=> false 
y.methods.include?("test_method") 
=> true 

Более конкретно,

x.singleton_methods 
=> [] 
y.singleton_methods 
=> ["test_method"] 

Любые идеи?

Ссылка:

http://www.ruby-doc.org/core/classes/Module.html#M001660 
http://www.ruby-doc.org/core/classes/Object.html#M000337 

ответ

3

Получил некоторую помощь от коллег, и понял, что мне нужно позвонить super еще это Нооп. Благодарю.

10

Вы должны использовать обратный вызов extended, а не переопределять extend_object. Первый вызывается, когда объект расширяется вашим модулем. Последний призван для фактического расширения объекта. Это как разница между included и append_features.

Вот пример:

module M1 
    def self.extended(base) 
    puts "extended object #{base.inspect}" 
    end 

    def test_method 
    true 
    end 
end 

Тогда:

>> (x = String.new).extend(M1) 
extended object "" 
=> "" 

>> x.methods.include?("test_method") 
=> true 
0

Кроме того, необходимо использовать символ, потому что имя метода является символом

module M1 
    def self.extend_object(o) 
    super 
    end 

    def test_method 
    true 
    end 
end 

(x = String.new).extend(M1) 

x.methods.include?(:test_method) #=> true