Ruby元编程,定义多个“继承”函数

5
我希望将以下模块包含在我拥有的类中:
module InheritanceEnumerator  
  def self.included(klass)  
      klass.instance_eval do  
        instance_variable_set('@subclasses',[])  
        def self.subclasses  
          @subclasses  
        end  
        original_method = self.respond_to?(:inherited) ? self.public_method(:inherited) : nil  
        instance_variable_set('@original_inherited_method', original_method)  
        def self.inherited(subclass)  
          @original_inherited_method.call(subclass) if @original_inherited_method  
          @subclasses<<subclass  
        end  
      end  
   end  
end  

我想要实现的是让我的父类有直接子类的引用。同时,我需要其他继承方法在我的类中仍然保持不变。我做错了什么?


你具体遇到了什么错误? - horseyguy
原始方法没有被调用。 - Olivier Tremblay
1个回答

2
您的代码在这种情况下运行正常(对我而言):
class C; include InheritanceEnumerator; end
C.subclasses #=> []
class C1 < C; end
class C2 < C; end
C.subclasses #=> [C1, C2]

但在以下情况下会失败:
class C11 < C1; end
C1.subclasses => NoMethodError: undefined method `<<' for nil:NilClass

这是因为只有在包含模块时才会初始化@subclasses,但您忘记了C的子类也可以访问模块方法,但不会显式地include它。
您可以通过以下方式解决这个问题:
def self.subclasses
    @subclasses ||= []
    @subclasses
end

def self.inherited(subclass)
    @original_inherited_method.call(subclass) if @original_inherited_method

    @subclasses ||= []
    @subclasses << subclass  
end

编辑:

好的,在未来,请更详细地说明您的问题并提供您正在使用的测试代码;因为这是一种令人沮丧的练习。

以下代码与您的代码完全兼容:

class C
    def self.inherited(s)
        puts "inherited by #{s}!"
    end

    include InheritanceEnumerator
end

class D < C; end #=> "inherited by D!"
C.subclasses #=> [D]

也许你的问题出在你在定义inherited方法之前就引用了InheritanceEnumerator

这是预期的行为,我不一定希望子类跟踪其子类。即使声明另一个“继承”函数,它是否有效? - Olivier Tremblay
@MrZombie,更新的答案解决了你的问题吗? :) - horseyguy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接