When declaring a case object, make it
final
.
While case objects are effectively final
in Scala - you can’t extend them - they are not always flagged as such in the compiled bytecode.
Take the following code, for example:
class Test {
case object foo
}
When foo
is not flagged as final
, running the class file through javap -c
yields the following (truncated) output:
public class Test$foo$ implements scala.Product,scala.Serializable {
// [...]
When it’s flagged as final
, however, we get:
public final class Test$foo$ implements scala.Product,scala.Serializable {
// [...]
To make matters worse, this is not even coherent accross Scala versions - the previous output was obtained with 2.12.7, but 2.11.8, for example, will compile both versions of Test.foo
as final
.
This might not seem like a big deal - as far as scalac
is concerned, Test.foo
is final
either way and you won’t be able to extend it - not having this information in the bytecode will:
final
-specific optimisationsjavac
will let you extend Test.foo
.