Можно ли повернуть включенный модуль в классе? - PullRequest
9 голосов
/ 19 июня 2009

Вы включаете модули в классы для расширения функциональности класса с точки зрения как добавления методов класса, так и методов экземпляра в этот конкретный класс.

module M
 def self.class_method_from_module
  'from class_method_from_module'
 end

 def instance_method_from_module
  'from instance_method_from_module'
 end
end

class C
 include M

 def self.class_method
  'from class_method'
 end

 def instance_method
  'from instance_method'
 end
end

puts C.class_method => 'from class_method'

puts C.class_method_from_module => 'from class_method_from_module'

puts C.new.instance_method => 'from instance_method'

puts C.new.instance_method_from_module => 'instance_method_from_module'

Теперь даже после удаления модуля M из памяти со следующим:

Object.send(:remove_const, :M) #remove the module M

puts C.class_method_from_module => 'from class_method_from_module'

puts C.new.instance_method_from_module => 'instance_method_from_module'

вместо метода отсутствует. Это почему? Каков наилучший способ удалить функциональность, добавленную модулем в класс?

Ответы [ 2 ]

9 голосов
/ 20 июня 2009

Детали варьируются в зависимости от реализации, но я знаю, что, по крайней мере, в JRuby и MRI 1.8 есть конструкция, которая называется «Включить класс», которая вставляется в цепочку наследования класса при расширении или включении модуля. Поэтому модуль не будет собирать мусор, так как класс Include по-прежнему ссылается на него, а методы по-прежнему будут в вашем классе. Об этом и связанных с ним темах есть несколько замечательных статей Патрика Фарли в его блоге .

Итак, чтобы «удалить» модуль, вы могли бы по отдельности отменить определение каждого метода, полученного из модуля, но для этой цели это довольно громоздкий механизм. Если использование камня приемлемо для вас, вероятно, было бы лучше использовать Mixology , который был разработан специально для динамического добавления и удаления модулей.

5 голосов
/ 19 июня 2009

Когда вы включаете миксин в класс, вы фактически добавляете методы, определенные в модуле, в класс или заменяете методы в классе на методы в модуле с тем же именем. Класс не связан с модулем, поэтому «отмена определения» модуля M не повлияет на класс C. Все, что вам нужно, это помешать вам смешать M за пределами этой точки.

Вы можете использовать undef_method для удаления методов из класса C, но это может иметь побочные эффекты, потенциально - если метод был переопределен путем добавления модуля, вы не получите исходный назад, например. Отмена определения метода класса довольно уродлива.

C.send(:undef_method, :instance_method_from_module)
class << C
  self
end.send(:undef_method, :class_method_from_module)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...