2017-02-14 3 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) 

? この場合、valueクラスを使用する利点はありますか(追加のメソッドはありません)?

答えて

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 caseクラスは、そのコンストラクタの引数として任意の文字列を取ります。 しかし、あなたはあなたの子供のクラス値型

case class PersonId(id: String) extends AnyVal 

でPERSONIDを宣言するかどうかが唯一の引数としてPERSONID、これがただの文字列ではなく、実際のP​​ERSONIDではないという事実を伝えるこの方法を受け入れます。

通常のケースクラスに対してAnyValを拡張する利点は、ほとんどの場合実行時オーバーヘッドがないことです。 詳細はlinkをチェックアウトできます。

関連する問題