2013-11-20 152 views
2

我測試元編程,我有一個情況下,我不明白:模塊擴展和class_eval紅寶石

module Bar 
def self.append_features klass 
    klass.class_eval do 
    def self.a 
     puts 'a' 
    end 
    end 
end 
end 

class Foo 
extend Bar 
end 

哪裏是界定「一」的方法? 因爲:

Foo.new.a,Foo.a和Class.a不起作用!如果我使用include而不是Foo類的擴展,方法「a」定義爲Foo類(Foo.a作品),我認爲:如果include爲「self」,Class =「self」爲extend = Metaclass,但沒有。

能解釋方法「a」在哪裏?

回答

6

append_features是紅寶石中的鉤子方法,當你做了include Bar時,它被調用。現在它將類方法a添加到類Bar,然後它使類方法aFoo可用。

讓我來解釋一下a如何成爲Bar的類方法。當您執行了include Bar時,將調用掛接方法,並將其參數klass設置爲Bar。現在klass.class_eval {..},class_eval設置self塊內{..}Bar。現在def self.a;puts 'a';end實際上意味着def Bar.a;puts 'a';end

module Bar 
def self.append_features klass 
    klass.class_eval do 
    def self.a 
     puts 'a' 
    end 
    end 
end 
end 

class Foo 
include Bar 
end 

Foo.a # => a 

哪裏是界定 「一」 的方法?因爲:Foo.new.a,Foo.a和Class.a不起作用!

這是因爲你做了extend Bar,它沒有調用鉤子方法append_features。正如你所期望的那樣,類的類方法還沒有在類Bar中定義。

+1

+1有趣! :)不知道'append_features';從來沒有想過關於'extend'和'include'的區別。 – kiddorails

+0

@kiddorails這是一個聰明的主意,因爲有一個簡單的'ri append_features'甚至'ri Module.append_features'可以給你提供足夠的信息,然後發佈到SO上;} –

+0

你變得相當不錯:-) –

1

「當這個模塊是包含在另一個,Ruby調用此模塊中append_features」(docs) - 你extended酒吧,不included酒吧。包含和擴展做了一些不同的事情,除了改變self的定義之外 - 例如,它們的鉤子方法是不同的。我懷疑append_features永遠不會被呼籲在你的情況下,你extend酒吧。