How do I call an auxiliary base-class constructor from a derived-class auxiliary constructor in Scala?

372 views Asked by At

You can call an auxiliary constructor in the base class via the derived class primary constructor:

class Base(n:Int) {
    def this(n:Int, i:Int) = {
        this(n)
        println(i)
    }
}

class Derived(n:Int, i:Int) extends Base(n, i)

Is there a syntax for calling an auxiliary base-class constructor from an auxiliary derived-class constructor? This doesn't work:

class Derived2(n:Int) extends Base(n) {
    def this(n:Int, i:Int) = {
        super.this(n, i) // Can't do this
        println(i)
    }
}

In other languages, you can do this, but you must call the base-class constructor first, which is why I tried to do it here.

Note that I am looking for the syntax for the call rather than alternative ways to achieve the same result.

1

There are 1 answers

1
Noah On BEST ANSWER

In Scala you have to go through the default constructor no matter what, which forces you to choose one super construction in your class instantiation. This is basically what you're trying to do in terms of java:

public class Derived2 extends Base {
    public Derived2(int n, int i) {
        super(n, i);
    }
    public Derived2(int n) {
        super(n);
    }
}

Since in Scala you have to go through the default constructor this is what's happening:

public class Derived2 extends Base {
    public Derived2(int n, int i) {
        this(n);
        super(n, i); //does not compile
    }
    public Derived2(int n) {
        super(n);
    }
}

So, as is normal in Java, you can only call super or this as the first line of your constructor implementation. Since Scala forces the call to the default constructor, there's no way around only using one implementation of the Base constructor.

There is no work around, as this isn't really dogmatic Scala. I would suggest changing your design here. Inheritance in Scala is usually done through traits, not classes or abstract classes.

Here's what an alternative might look like using a trait:

  trait Base2 {
    val a:Int
  }

  class Derived3(n: Int) extends Base2 {

    val a = n

    def this(n: Int, i: Int) = {
      this(n)
    }
  }