【问题标题】:Is it possible to reverse the included module in a class?是否可以反转类中包含的模块?
【发布时间】:2009-06-19 18:43:26
【问题描述】:

您将模块包含在类中以扩展类功能,即向该特定类添加类方法和实例方法。

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'

而不是缺少方法。这是为什么?删除模块添加到类的功能的最佳方法是什么?

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    细节因实现而异,但我知道至少在 JRuby 和 MRI 1.8 中有一个称为 Include Class 的构造,当扩展或包含 Module 时,它​​会插入到类的继承链中。因此,模块不会被垃圾收集,因为 Include Class 仍然引用它,并且方法仍然在您的类上。 his blog 中有 Patrick Farley 撰写的关于此和相关主题的一些精彩文章。

    因此,要“删除”一个模块,您可以单独取消定义来自该模块的每个方法,但为此目的,这是一个相当笨拙的机制。如果您可以接受使用 gem,最好使用 Mixology,它是专门为动态添加和删除模块而设计的。

    【讨论】:

    • Mixology 链接有错字(在 url 中加倍了 y)。但谢谢你!
    【解决方案2】:

    当你在一个类中包含一个 mixin 时,你实际上是将模块中定义的方法添加到类中,或者将类中的方法替换为模块中具有相同名称的方法。该类与模块没有任何联系,这就是为什么“取消定义”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)
    

    【讨论】:

    • 感谢丹尼尔的反馈。我的理解是,当您在对象上调用方法时,它会查找按顺序定义的方法(1)该特定对象的元类(2)其类(3)包含模块(4)超类(5)超类包含模块和依此类推,所以当我包含一个模块并且如果它有效地添加了这些方法时,ruby 如何知道哪个方法属于元类、类、模块等等......我认为通过 mixin 模块,ruby 会保留对该特定模块,通过删除常量,它应该有效地删除引用。
    • 据我了解,没有保留对模块的引用;混合发生,然后模块成为(可以这么说)类的一部分。因此,即使您删除了模块,该类仍然保留混合的方法/属性。
    • 必须有一些对模块的引用(某种知识,该方法在模块中定义或某种类型)保存在内存表中,否则 ruby​​ 怎么知道在哪里寻找当方法实际上没有在类中定义时的层次结构链。不过感谢您的反馈。
    猜你喜欢
    • 2017-05-29
    • 2011-08-29
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    • 2015-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多