Search code examples
classscalaabstracttraitsself-type

Self-type annotation hinders instantiation of inner class. Why?


Given the abstract definitions of the Outer class and its Inner class I would like to instantiate the concrete Inner1 class defined within Outer1 trait.

abstract class Outer {
  type Inner_Tp <: Inner;
  abstract class Inner {
    self: Inner_Tp =>
  }
}

trait Outer1 {
  self: Outer =>
  protected class Inner1 extends Inner {
    self: Inner_Tp =>
  }
  def Inner1() = new Inner1()
}

The Scala compiler prematurely terminates the compilation giving me the following error message: "error: class Inner1 cannot be instantiated because it does not conform to its self-type Outer1.this.Inner1 with Outer1.this.Inner_Tp". Why?

After all the Inner1 class is defined within an abstract context being its Outer1 trait. I would like to postpone the definition of type Inner_Tp until the trait gets mixed into some concrete class.


Solution

  • For Inner1, the self-type says that it will always be instantiated together with the abstract type Inner_Tp. That's a promise that is not fulfilled at the instantiation point: the type is only Inner1 instead of Inner1 with Inner_Tp.

    If you need to delay the definition of Inner_Tp, you also need to delay the creation of any instances that have it as a self-type. That is absolutely necessary, since you cannot produce a value of a type that you don't know yet. So better leave the method abstract. You may refine the abstract type as well:

    trait Outer1 extends Outer {
       type Inner_Tp <: Inner1
       protected class Inner1 extends Inner
    
       def Inner1(): Inner_Tp
    }
    

    I'm not sure what you are after, but you may not need the self-types at all (I left them out for brevity already).