Расширение рубинового объекта; Обратный вызов extend_object предотвращает расширение методов экземпляра - PullRequest
2 голосов
/ 22 мая 2009

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

(s = String.new) .extend SomeModule

Вызывается обратный вызов SomeModule extension_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 ]

10 голосов
/ 22 мая 2009

Вы должны использовать обратный вызов 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
3 голосов
/ 22 мая 2009

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

0 голосов
/ 29 апреля 2012

Также вам нужно использовать символ, потому что имя метода - символ

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...