2012-10-29 30 views
23

私はScala Enumerationが型安全ではないという多数のアサーションを見てきました。どのようにタイプセーフなのですか? 1つのEnumerationの値を別のEnumerationに渡すことができないという点で、型の安全性は明らかです。Scala:列挙型は型安全ではありません。

Enumerationで回避しなければならない落とし穴は何ですか?

答えて

33

セミセーフです。タイプセーフであることはコンパイラフィクションなので、簡単に破ることができます。たとえば、

trait Parent 
class Boy extends Parent { override def toString = "boy" } 
class Girl extends Parent { override def toString = "girl" } 
def f(g: Girl) = g.toString 

scala> f((new Boy).asInstanceOf[Girl]) 
java.lang.ClassCastException: Boy cannot be cast to Girl 
    at .<init>(<console>:15) 
    ... 

いいえ、男の子は女の子ではありません。

今度は、列挙してみましょう:

object Test extends Enumeration { val One, Two = Value } 
object Probar extends Enumeration { val Uno, Dos = Value } 
def h(tv: Test.Value) = tv.toString 

scala> h((Probar.Uno).asInstanceOf[Test.Value]) 
res0: java.lang.String = Uno 

待って、何?

この小説は、他の奇妙な行動につながる:

def h(pv: Probar.Value) = pv.toString // Add this to the other h in a :paste 

method h:(pv: Probar.Value)java.lang.String and 
method h:(tv: Test.Value)java.lang.String at line 9 
have same type after erasure: (pv: Enumeration#Value)java.lang.String 
      def h(pv: Probar.Value) = pv.toString 

ええと、大丈夫、おかげ?その後、

とコンパイラが本当に独自の構造としてEnumerationを理解していないので、それはあなたが期待するかもしれない方法であなたを助けることはできません。

scala> def oops(tv: Test.Value) = tv match { case Test.One => "okay" } 
oops: (tv: Test.Value)java.lang.String 
// No incomplete match warning? Okay.... 

scala> oops(Test.Two) 
scala.MatchError: Two (of class scala.Enumeration$Val) 
    at .oops(<console>:8) 
    ... 

だから、あなたは正確に比較的限られた方法でそれを使用する場合意図したとおり、型の安全性を提供します。しかし、それはこのような他のパターンの力と頑強さを持っていません:

// In REPL, :paste the next three lines 
sealed trait Foo 
object Bar extends Foo 
object Baz extends Foo 

scala> def safe(f: Foo) = f match { case Bar => "okay" } 
<console>:9: warning: match is not exhaustive! 
missing combination   Baz 

     def safe(f: Foo) = f match { case Bar => "okay" } 
         ^

ありがとう、コンパイラ!

関連する問題