23
私はScala Enumerationが型安全ではないという多数のアサーションを見てきました。どのようにタイプセーフなのですか? 1つのEnumerationの値を別のEnumerationに渡すことができないという点で、型の安全性は明らかです。Scala:列挙型は型安全ではありません。
Enumerationで回避しなければならない落とし穴は何ですか?
私はScala Enumerationが型安全ではないという多数のアサーションを見てきました。どのようにタイプセーフなのですか? 1つのEnumerationの値を別のEnumerationに渡すことができないという点で、型の安全性は明らかです。Scala:列挙型は型安全ではありません。
Enumerationで回避しなければならない落とし穴は何ですか?
セミセーフです。タイプセーフであることはコンパイラフィクションなので、簡単に破ることができます。たとえば、
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" }
^
ありがとう、コンパイラ!