2017-02-14 45 views
4

比方說,我有這樣的ADT:是否有利用價值類(沒有方法)與類型別名?

case class Person(id: String) 
case class Kid(id: String, name: String) 

我謹代表中更明確和類型安全的方式ID場。我有兩個選擇

1.類型別名

type PersonId = String 
case class Person(id: PersonId) 
case class Kid(id: String, name: PersonId) 

2.值類

case class PersonId(id: String) extends AnyVal 
case class Person(id: PersonId) 
case class Kid(id: String, name: PersonId) 

哪種方法更地道? 在這種情況下使用值類有沒有任何優勢(沒有額外的方法)?

回答

3

類型別名純粹是語法上的方便,在某些情況下,他們可以使代碼更清潔或更容易重構,但他們不提供任何額外的類型安全。例如,假設我有一些像這樣的代碼:

type DegreesC = Double 
type DegreesF = Double 

def c2f(c: DegreesC): DegreesF = (c * 9.0/5.0) + 32 

和代表華氏當前溫度值:

val currentTempInF = 62.0 

編譯器是高興,讓我這個傳遞給我的c2f方法:

scala> c2f(currentTempInF) 
res1: DegreesF = 143.6 

值班給你更多的類型安全而無需爲案例類的額外分配的運行成本(雖然還有一個語法成本) :

case class DegreesC(value: Double) extends AnyVal 
case class DegreesF(value: Double) extends AnyVal 

def c2f(c: DegreesC): DegreesF = DegreesF((c.value * 9.0/5.0) + 32) 

val currentTempInF = DegreesF(62.0) 

然後:

scala> c2f(currentTempInF) 
<console>:14: error: type mismatch; 
found : DegreesF 
required: DegreesC 
     c2f(currentTempInF) 
     ^

你喜歡的口味的問題。就我個人而言,我認爲Scala中的類型別名經常被濫用和超賣,但我也傾向於避免使用價值類,因爲它們具有奇怪的限制和錯誤,而且它們提供的運行時性能優勢對我來說並不重要。無論如何,我不會說一種方法,或者另一種更習慣(如果有的話我會將這種狀態提供給一個簡單的,無價值的類案例課)。

0

類型別名僅提供別名,但沒有類型安全性。

type PersonId = String 
case class Person(id: PersonId) 

Person("some random string") 

編譯和運行沒有錯誤

case class PersonId(id: String) extends AnyVal 
case class Person(id: PersonId) 

Person("some random string") 

在編譯時失敗,出現錯誤類型

2

針對您的特定用例(無其他方法)。類型安全是最大的優勢。如果您聲明PersonId是這樣的類型

type PersonId = String 

您的Kid案例類將採用任何字符串作爲其構造函數的參數。 但如果你將宣佈PERSONID值類型

case class PersonId(id: String) extends AnyVal 

你小子類只接受PERSONID作爲參數,這樣你溝通的事實,這是不是任何字符串,但實際PERSONID。

將AnyVal擴展到常規case類的優點是它在大多數情況下不會帶來運行時開銷。 您可以結算此link瞭解更多詳情。

相關問題