2016-02-29 77 views
0

如何編寫一個ruby模塊,對包含它的類施加一些條件,這些條件必須滿足當前打開的類定義的末尾?ruby​​模塊如何對包含它的類執行條件?

要具體,假設條件是「一個類變量@@foo應該被定義爲> 0」

我想寫一個模塊,看起來是這樣的:

module NeedPositiveFoo 
    module ClassMethods 
    def validate_positive_foo 
     raise unless defined?(@@foo) && @@foo > 0 
    end 
    end 

    def included(other) 
    other.extend(ClassMethods) 
    end 
end 

那麼這個類的定義是有效的:他們的收盤end的後

class ValidClass 
    include NeedPositiveFoo 
    @@foo = 3 
end 

但這些類定義將提高:

class InvalidClass1 
    include NeedPositiveFoo 
    # @@foo is not defined 
end 

class InvalidClass2 
    include NeedPositiveFoo 
    @@foo = -2 
end 
+3

沒有「類定義的末尾」這樣的東西。隨時可以在任何時候打開課程主體。或者如果你的意思是語法級別,那麼你可以使用TracePoint。 – sawa

+0

@sawa這是不正確的。有「當前打開的類定義的結束」這樣的東西,適用於'included'回調中。 – mudasobwa

+0

@mudasobwa你指的是語法級別。你說得對,但我的意思是另一回事。 – sawa

回答

4

雖然由烏里阿加西的答案時,你是完美的作品允許將類包含在類定義的最後,儘管放置了include,下面的代碼仍可以工作。

def included(other) 
    TracePoint.new(:end) do |tp| 
    if tp.self == other 
     tp.disable 
     raise unless defined?(other.class_variable_get(:@@foo)) # checks 
    end 
    end.enable 
    other.extend(ClassMethods) 
end 

TracePoint documentation

+0

這也許是解決OP問題的唯一方法。雖然,這個問題是一個XY問題。 – sawa

+0

@sawa是的。至少,除此之外,我找不到任何工作解決方案。 – mudasobwa

4

不能掛鉤類定義的結束,因爲沒有一個 - 一類可以在不同的文件中聲明,在不同的時間,而在偶數不同的庫。

你可以做什麼,是檢查車況當模塊包括,在您定義的最後聲明中包含:

module NeedPositiveFoo 
    def included(other) 
    raise unless defined?(@@foo) && @@foo > 0 
    end 
end 

class ValidClass 
    @@foo = 3 
    include NeedPositiveFoo 
end 

class InvalidClass1 
    # @@foo is not defined 
    include NeedPositiveFoo 
end 

class InvalidClass2 
    @@foo = -2 
    include NeedPositiveFoo 
end 

class InvalidClass3 
    include NeedPositiveFoo 

    @@foo = 4 # declared after inclusion - not a valid state... 
end 
2

當問這樣的問題時,通常看看Ruby核心庫如何去做。有在Ruby核心庫兩種衆所周知的混入,其放置在類的某些條件下,它們被混合到:

  • Enumerable要求類具有each方法可以與零個參數調用,並採取了塊,它將連續收集所有的元素。
  • Comparable要求類具有<=>方法,其可與一個單一的參數來調用,並用響應任一-10,或1,這取決於參數是否被認爲是比該接收器大於,等於或小於。

在這兩種情況下,只需在文檔中說明要求,而不是在代碼中說明。由班級作者來確保他們得到滿足。

事實上,在Enumerable情況下,需求是不是真的在所有說,它只是假設,任何有能力的Ruby程序員都知道他們。

我會遵循核心庫的作者設定的這種風格,因爲它是Rubyists習以爲常的。

相關問題