Search code examples
scaladependent-typepath-dependent-type

Path-dependency and inner classes


Following sample code fails to compile with the error listed below.

class Outer {
  class Inner

  val instance: Inner = new Inner

  def verify(pd: Inner): Boolean = pd == instance
}

class UseOuter(val pdp: Outer) {
  def foo: pdp.Inner = pdp.instance
}

class UseCase {
  val pdp = new Outer
  val user = new UseOuter(pdp)

  val i = user.foo

  pdp.verify(i)
}

Error:

test.sc:19: type mismatch;
 found   : UseCase.this.user.pdp.Inner
 required: UseCase.this.pdp.Inner
  pdp.verify(i)
             ^
Compilation Failed

I'm not entirely sure but reading Inner Classes suggests that it's the intended behaviour? Specifically the following sentence:

As opposed to Java-like languages where such inner classes are members of the enclosing class, in Scala such inner classes are bound to the outer object.

If that's the case and this is indeed the desired behaviour, is there a way to encode this requirement in Scala?

There are a few similar questions but they all concern inner types, and not classes and the proposed solutions will not apply.


Solution

  • For example you can use type projections:

    class Outer {
      class Inner
    
      val instance: Inner = new Inner
    
    //  def verify(pd: Inner): Boolean = pd == instance
      def verify(pd: Outer#Inner): Boolean = pd == instance
    }
    
    class UseOuter(val pdp: Outer) {
    //  def foo: pdp.Inner = pdp.instance
      def foo: Outer#Inner = pdp.instance
    }
    
    class UseCase {
      val pdp: Outer = new Outer
      val user: UseOuter = new UseOuter(pdp)
    
    //  val i: user.pdp.Inner = user.foo
      val i: Outer#Inner = user.foo
    
      pdp.verify(i)
    }