Search code examples
scalainheritancemodifier

Use of Scala's private final modifier?


What can I use the private final modifier in Scala for?

Given the below code:

1| class A { def callFoo = foo; private final def foo = "bar of A" }
2| class B extends A { private final def foo = "bar of B"}
3| println((new A()).callFoo)
4| println((new B()).callFoo)

Line 3 and 4 prints:

1| bar of A
2| bar of A

It is understandable why line 2 doesn't print bar of B because there are actually two foo definitions and the latter in B doesn't override the former in A. Otherwise Scala would require the override- instead of the final modifier.

So why does Scala not simply forbid the combination of the modifiers private final?


Solution

  • Ok, this is tricky. Your question: "So why does Scala not simply forbid the combination of the modifiers private final?" is based on the assumption that this combination has no use.

    Let's say you are right (and you are, except for a tiny detail, which will be mentioned later). I'm not a compiler guy, but from my point of view "simply forbid" is probably not that simple at all (at least in this case). And why would someone attempt to do it? What are the trade-offs? Only because something is not useful does not necessarily mean that it does any harm. Just don't use it...

    Now here comes the tiny detail you seem to have overlooked. The private modifier is a visibility modifier, which means class B is unaware of it's existence. But Scala's visibility modifiers are a bit more complex, than say, Java's. Let's assume that for whatever reason you would require code shown in the following code snippet, the compiler will not allow it.

    package scope
    
    class A {
      def callFoo = foo;
      private[scope] final def foo = "bar of A"
    }
    class B extends A {
      private[scope] final def foo = "bar of B"
    }
    
    object Main extends App {
      println((new A()).callFoo)
      println((new B()).callFoo)
    }
    

    This is one of the errors provided by the compiler: "method foo cannot override final member".

    So here you go. Scala simply forbids this combination ;)