2016-05-26 28 views
2

考虑以下Ruby类的示例,该示例包含一个定义类和实例方法的模块以及一个继承第一个类的第二个类。Ruby模块可以定义类方法,所以它们也可以在模块嵌套时工作吗?

module Z 
    def self.included(base) 
    class << base 
     def classmethod 
     puts "Hello, I'm #{__method__} in #{self}" 
     end 
    end 
    end 
    def instancemethod 
    puts "Hello, I'm #{__method__} in #{self}" 
    end 
end 

class A 
    include Z 
end 

class B < A 
end 

A.classmethod 
A.new.instancemethod 
B.classmethod 
B.new.instancemethod 

输出如预期:类和实例都具有由模块定义的方法。

Hello, I'm classmethod in A 
Hello, I'm instancemethod in #<A:0x85f4c10> 
Hello, I'm classmethod in B 
Hello, I'm instancemethod in #<B:0x85f4968> 

现在,考虑上述模块包含在另一个模块的情况下,其类别包括代替:

module Y 
    include Z 
end 

class C 
    include Y 
end 

class D < C 
end 

Y.classmethod 
C.classmethod 
C.new.instancemethod 
D.classmethod 
D.new.instancemethod  

的实例方法的工作,但对CD类的方法不(在在替代模块Y中替代地定义了classmethod)。

能模块Z被修饰的,使得类的方法被添加到类C而不是中间模块,Y

原始场景(即模块没有嵌套的地方)也应该继续像上面那样工作。

+0

调用'在'module' include'那刚好碰巧包含了一些东西并不意味着你会得到'include'依赖关系来链接。将模块包含在模块中并不完全符合您期望的模块。 – tadman

+0

你会接受一个回答吗?除了'包括Z'之外,还有其他的方法吗? – Raffael

+1

'ActiveSupport :: Concern'可以帮助你在这里(Z和Y都必须扩展它)。这对你来说是一种选择吗? – Raffael

回答

0

试试这个。

module Y 
    def self.included(base) 
    Z.included(base) 
    end 
end 

class C 
    include Y 
end 

class D < C 
end 

Y.classmethod 
    #=> NoMethodError: undefined method `classmethod' for Y:Module 

C.classmethod 
    #=> Hello, I'm classmethod in C 

C.new.instancemethod 
    #=>Hello, I'm instancemethod in #<C:0x007ff58403d370> 

D.classmethod 
    #=> Hello, I'm classmethod in D 

D.new.instancemethod  
    #=> Hello, I'm instancemethod in #<D:0x007ff5842478f0> 

四分之五不坏,呃?我现在已经没有时间了,但会看看我是否可以让Y.classmethod工作。也许读者可能会有一个建议。

+0

太好了。 'Y.classmethod'不需要。我明天会测试一下。我正在做这样的事情,但我一定做错了什么。它确实需要'Y'被修改,但我怀疑这是可以避免的。 – starfry

0

@卡里 - swoveland的想法使我试试这个,它解决了原来的问题:它是Z当它被嵌套在一个可行的修改:

module Z 
    def self.included(base) 
    class << base 
     def classmethod 
     puts "Hello, I'm #{__method__} in #{self}" 
     end 
     def included(base) 
     Z.included(base) 
     end 
    end 
    end 
    def instancemethod 
    puts "Hello, I'm #{__method__} in #{self}" 
    end 
end 
相关问题