2015-02-07 24 views
1

我嘗試將以下特徵混合到我的類中,以享受類似Boolean類型的行爲。如何使用閉集的值創建您自己的類型,在Scala

trait ReadyStates { // well, this is really used like an enumeration 
    class ReadyState 
    object Ready extends ReadyState 
    object NotReady extends ReadyState 
} 

但是,這不起作用,因爲這個特徵混入的每個類都創建它自己的對象。所以當在不同類的成員之間傳遞返回值時,Ready不可能天真地與Ready比較。

我怎樣才能得到一個自定義類型,它有自己的一組允許值,與布爾值相同truefalse,它們可以跨類進行無縫比較?

我看了一下枚舉,他們當時看起來並不很亮。

謝謝!

+3

似乎'ReadyStates'應該只是一個'object',其他類只是使用它的子類型?另外考慮讓'ReadyState'密封和抽象。 – 2015-02-07 21:17:09

+0

這意味着'ReadyStates.Ready'需要使用的地方。不太像「真」和「假」。但是,它的工作原理! – matanster 2015-02-07 21:23:25

+1

如果你輸入了blah.package.name.ReadyStates._' – 2015-02-07 21:24:33

回答

5

用@米-Z的評論的鼓舞下,我最終使用:

sealed abstract class ReadyState 
object Ready extends ReadyState 
object NotReady extends ReadyState 

沒有任何包裝對象。簡單。

+1

,那麼不行。這就是代數和類型在Scala中的編碼方式。作爲例子,請看'Boolean','List'等。事實上,這幾乎是「密封」存在的唯一原因。 – 2015-02-07 22:19:20

+2

我寫了一個關於Scala中正確的面向對象的布爾類型的小實現,在Programmers.SE的回答中看起來像是這樣,如果你感興趣的話:http://programmers.stackexchange.com/a/266635/1352 – 2015-02-07 22:23:15

+0

@JörgWMittag ..不確定Scala是如何實現布爾值的,那麼..它的值是否只是擴展它的類型,或者類似於代碼中的類型?他們感覺像某種類型的文字而不是類型,按照'true.getClass'的REPL。現在只是好奇。 – matanster 2015-02-08 14:07:50

3

爲了進一步擴展馬特的回答,我通常會做:

sealed trait ReadyState 
object ReadyState { 
    case object Ready extends ReadyState 
    case object NotReady extends ReadyState 
} 

包裝紙的情況下的陪伴對象的對象ReadyState避免命名空間污染。比如現在你可以有另一種ADT,像

sealed trait AnotherState 
object AnotherState { 
    case object Ready extends AnotherState 
    case object NotReady extends AnotherState 
} 

ReadyNotReady名稱將不會發生衝突,因爲他們是「命名空間」的各個物體下。

此外,使用case objects(或類)允許編譯器檢查詳盡的匹配。