Почему мы можем создавать новые классы, производные от sealed(scala) в Java?
Рассмотрим два класса A и B:
// A.scala
object A {
sealed abstract class Nat
case object Zero extends Nat
case class Succ(n : Nat) extends Nat
def pp(n : Nat) = n match {
case Zero => println("Zero")
case Succ(m) => println("Succ")
case _ => println("WTF")
}
def main(args : Array[String]) =
pp(B.f())
}
// B.java
public class B {
static A.Nat f() {
return new A.Nat() {};
}
}
Скомпилируйте, запустите:
$ scala A
WTF
Как сказано в документации: "Запечатанный класс не может быть унаследован напрямую, кроме случаев, когда шаблон наследования определен в том же исходном файле, что и унаследованный класс".
Я думал, что это означает, что сопоставления с образцом через подклассы, определенные в одном и том же файле, достаточно, чтобы охватить все случаи, но, как мы видим из этого примера, это не так.
Вот вопрос: есть ли способ написать действительно закрытые классы (например, ADT), или мне нужно писать фиктивный последний случай в каждом совпадении с шаблоном, чтобы обеспечить безопасность кода?
1 ответ
Их можно создать из Java, поскольку детали, которые закрывает класс Scala, учитываются только самим компилятором Scala. Компилятор Java не имеет понятия, что A.Nat вообще запечатан.
Также в качестве дополнительного примечания вам нужно пометить Succ как запечатанный, так как в противном случае даже в Scala кто-то может его расширить.