2014-11-03 146 views
6

當分配不同的類型別名共享相同的基礎類型時有沒有辦法獲得編譯時錯誤(或至少警告)?斯卡拉:強制編譯錯誤類型別名不匹配

換句話說,說我有這樣的代碼:

type Address = String 
type City = String 

def foo(x:Address) = ... 

我希望得到一個編譯時錯誤/警告,如果我做的:

val city: City = "Dublin" 
foo(city) 

據我所知道的,編譯器允許它,因爲它們是相同的基礎類型。

回答

4

據我所知,不可能獲得您尋求類型別名的「類型安全性」。但是,有一種替代方法可以用於你想要的別名:Value Classes。基本上,一個值類可以給你一個類型,而不分配一個新的對象。請注意,對於類型別名不具有的值類有一些限制。

引述斯卡拉文檔:

正確性

另一個用例的值類是得到一個數據類型的類型安全沒有運行時分配開銷。例如,表示距離數據類型的片段可能看起來像:添加兩個距離

class Meter(val value: Double) extends AnyVal { 
    def +(m: Meter): Meter = new Meter(value + m.value) 
    } 

代碼,如

val x = new Meter(3.4) 
    val y = new Meter(4.3) 
    val z = x + y 

實際上不會分配任何Meter實例,但只會在運行時使用原始雙精度。

+0

我可以創建價值案例類嗎?我有點不喜歡新的關鍵字使用 – 2014-11-03 17:57:06

+0

您可以定義值案例類。順便說一句:你可以省略'new'-關鍵字的原因是(生成的)伴侶對象的'apply'-方法,所以你不一定需要定義一個case類來擺脫關鍵字。 – 2014-11-03 22:07:33

+0

是的我知道,我只是不想爲所有類型的別名定義我自己的同伴,它很長很枯燥^ _ ^ – 2014-11-04 10:01:47

3

號至少,不是沒有修改編譯器(它可能有可能與編譯器插件,甚至是微距),如果你做這個改變,然後有很多流行的庫(包括標準庫)和標準代碼示例不會編譯。

您可能喜歡使用值類,如@ Kulu的答案中所述。或者,Scalaz Tagged Types可避免更多情況下的開銷(例如,將它們置於集合中,或使用subst安全地上傳使用標記類型的泛型類型)。