Search code examples
scalainheritancechaining

Why Scala reports error if does not specify this.type when using chain method in inherited class


The following code working properly

abstract class Base {
  def append(value: Any): this.type = this
}

class Axis extends Base {
  def text(value: String): this.type = append(value)
}

class XAxis extends Axis {
  def position(value: Int): this.type = append(value)
}

def main(args: Array[String]): Unit = {
  new XAxis().text("hello").position(0)
}

While if I remove this.type in Axis.text

class Axis extends Base {
  // here we don't explicitly specify return type this.type
  def text(value: String) = append(value)
}

Scala report

value position is not a member of Axis.

The method call chain

new XAxis().text will call append

append has the return type this.type

this is an instance of XAxis.

So this.type is Axis

So no matter whether specify this.type as return type, Scala should be always possible to infer to the real instance type.

Why it works when we explicitly specify the return type this.type?

But it does not work when we don't explicitly specify the return type this.type?


Solution

  • When you don't specify the return type of a method, the compiler will infer it. More specifically the compiler will always infer the most precise type, but never a singleton type (which can be recognized by the value.type notation). So in this case the method text will be inferred to return something of type Axis, which is the most precise supertype of this.type in the class Axis.