scalamigrationscala-3

Double definition in Scala 3


Why this class is allowed in Scala 2.x and it complains of duplicated definition of a under Scala 3?

class A private(a:Int) {
   def a(): Int = this.a+1
}
       Double definition:
         private[this] val a: Int in class A at line 1 and
         def a(): Int in class A at line 2

It this by design or it is a bug in Scala 3?


Solution

  • class A private(a: Int) {
      def a(): Int = this.a + 1
    }
    

    TL;DR: In Scala 2 this creates a member and a method of A which are both called a, but Scala 3 doesn't allow this duplicate use of the same name.

    In Scala 2 there is a member a that contains the value that is passed to the constructor and a method a that returns this.a + 1. This can be shown by adding a second method b:

    class A(a: Int) {
      def a(): Int = a + 1
    
      def b(): Int = a() + 1
    }
    
    println(new A(3).a()) // 4
    println(new A(3).a)   // 4 with compiler warning about auto-application
    println(new A(3).b()) // 5
    

    Within the class you get different values for a depending on whether or not it is used bare or invoked as a function. Method a uses the member value a while method b uses the method value a. Outside the class only the method is visible.

    Note that this is specifically a problem with the behaviour of non-val non-var constructor parameters for a class. If the constructor parameter is made val or var the compiler will flag this as a duplicate even in Scala 2.