Nó bán an toàn. Đó là loại an toàn là một trình biên dịch viễn tưởng, do đó, nó rất dễ dàng để phá vỡ. Ví dụ:
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)
...
Được rồi, con trai không phải là con gái.
Bây giờ chúng ta hãy thử với kiểu liệt kê:
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
Chờ, gì?
tiểu thuyết này dẫn đến những hành vi kỳ lạ khác:
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
Uh, được rồi, nhờ?
Và rồi kể từ khi biên dịch không thực sự hiểu Enumeration
như cấu trúc riêng của nó, nó không thể giúp bạn theo những cách bạn có thể mong đợi:
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)
...
Vì vậy, nếu bạn sử dụng nó theo những cách tương đối hạn chế chính xác như dự định, nó cung cấp loại an toàn. Nhưng nó không có sức mạnh và sức mạnh của các mẫu khác, như thế này:
// 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" }
^
Cảm ơn, trình biên dịch!