2014-07-16 83 views
1

Ruby類比方說,我打算寫賽馬投注的應用,我想一個RaceResult類,可以有四個離散值:WinPlaceShow和「空對象」類Lose有限離散值

我來到紅寶石從C#的背景,我通常會使用enum這一點,或者是一系列由私人構造器創建的靜態只讀域,像這樣的:

public class RaceResult { 
    public static RaceResult Win = new RaceResult(1); 
    // ... 

    private int lowestPositionToWin; 

    private RaceResult(int position) { 
    lowestPositionToWin = position; 
    } 

    private bool PaysOut(int placement) { 
    return placement <= lowestPositionToWin; // logic may be flawed here 
    } 
} 

如果班太複雜了,我會重構使用策略模式。

什麼是一種很好的Ruby方法來解決這個需求?我可以創建一個只能有四個實例的類嗎?我在查詢Google查詢時遇到問題,無法找到我要查找的信息。

編輯:在第一個答案中,我已經得到了一些很好的方法來處理我只想要一個命名的原始值的情況。但是,如果我有興趣擴展它的行爲,我需要一個自定義類。有沒有一種方法可以修改常用的使用類的方法?

回答

1

this StackOverflow answer,發現搜索「紅寶石等同枚舉」的時候,你可以建立使用模塊和常量枚舉狀結構:

module RaceResult 
    LOSE = 0 
    WIN = 1 
    PLACE = 2 
    SHOW = 4 
end 

result = RaceResult::WIN 

這具有能夠使用bonust點對值進行按位運算符(例如RaceResult::WIN & RaceResult::SHOW),即使在此特定應用程序中可能不需要。

編輯:你甚至可以更進一步,定義一個枚舉創建功能代碼:

def Enum(values) 
    result = Module.new 
    i = 0 
    values.each do |name| 
     result.const_set name, 2**i 
     i += 1 
    end 
    return result.freeze 
end 

RaceResults = Enum ["LOSE", "WIN", "PLACE", "SHOW"] 

*雖然這個最小的實現,失去的是不是默認零值/空值對象,但。

實際類似C#的枚舉

在你編輯提到的,你還需要一些行爲(功能),所以你可能要到實際使用的一類。我要將第一個片段(使用手動定義的模塊)與this answer混合,所以我們仍然有通常的按位運算符可用,就像正常枚舉一樣。在下面的代碼片段中,第一個類定義創建了一個通用的Enum類,應該由任何實際枚舉繼承(這是枚舉的實現)。第二類是實際的枚舉,在我們的例子中,RaceResults。請注意,它繼承Enum,並使用構造函數定義其常量(稍後的更多內容)。它還定義了一個可以在其上調用的方法,就像一個例子。

class Enum 
    def initialize(n) 
     @value = n 
    end 

    def method_missing(name, *args, &blk) 
     ret = @value.send(name, *args, &blk) 
     ret.is_a? Numeric ? Enum.new(ret) : ret 
    end 
end 

class RaceResults < Enum 
    LOSE = self.new 0 
    WIN = self.new 1 
    PLACE = self.new 2 
    SHOW = self.new 4 

    def doSomething 
     puts "did something useful, and btw, numerically I am #{@value}" 
    end 
end 

RaceResults::WIN.doSomething 

在最後一行中,您可以看到如何使用定義的方法以及如何訪問常量值。

爲什麼使用構造函數來定義可能的值,你可能會問?那麼,主要是您仍然可以使用按位運算符(&,|等),同時可以從相同的值調用任何實例方法。它比使用轉換方法更透明一些,比實際實現運算符更懶惰。

+0

這更接近我想要的。我怎樣才能將每個常量分配給一個自定義對象? – neontapir

+0

@neontapir查看第一個代碼片段,在這兩種方法中,您只需使用'anyVariable = TheEnum :: SOME_CONSTANT'。第二個片段只是輕鬆生成這些「枚舉」的一種方法。 – Kroltan

+0

@neontapir我沒有閱讀你的編輯,對不起,我會嘗試擴展 – Kroltan

2

不知道我是否理解你的要求,但是如何處理更紅寶石的Hash

race_results = { win: 1, place: 2, show: 3, lose: 4 } 
+0

Hash解決了我擁有的只是一個值的情況。我更新了我的問題以顯示可能存在某些行爲。 – neontapir