Question

Consider two classes A and 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() {};
    }
}

Compile, run:

$ scala A
WTF

As said in the documentation, "A sealed class may not be directly inherited, except if the inheriting template is defined in the same source file as the inherited class."

I thought it implies pattern-matching through subclasses defined in the same file is enough to cover all cases, but as we can see from this example it's not true.

Here is a question: is there a way to write really sealed classes (like ADTs) or I need to write dummy last case in every pattern match to ensure code safety?

Was it helpful?

Solution

It's possible to create them from Java as the detail that a Scala class is sealed is only honoured by the Scala compiler itself. The Java compiler has no concept that A.Nat is sealed at all.

Also as a side note, you'll need to mark Succ as sealed, as otherwise even in Scala someone can extend it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top