2016-05-26 58 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 
相關問題