Scala:Enumeration怎么不安全?

时间:2012-10-29 20:45:20

标签: scala enums

我已经看到一些断言Scala Enumeration不是类型安全的。它怎么不安全?它显然是类型安全的,因为你不能将一个Enumeration的值传递给不同的Enumeration。

Enumeration要避免哪些陷阱或缺点?

1 个答案:

答案 0 :(得分: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" }
                           ^

谢谢,编译!