Simon K
Simon K

Reputation: 135

How do I constrain a member of a parameter class to match the instance of an outer class?

The following code does not compile, because the compiler cannot prove that v.o.Inner and Outer.this.Inner are the same, in the implementation of visit(). I cannot see how to tell the compiler than v.o must be Outer.this such that its recognized at compiler time. Any ideas?

class Outer {
   class Inner {
      def visit(v:Visitor) = v.visitInner(this)
   }
}

class Visitor(val o:Outer) {
    def visitInner(i:o.Inner) = { println("foo") } 
}

Upvotes: 4

Views: 70

Answers (1)

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297265

The compiler cannot prove that because that is false. For example:

val o1 = new Outer
val o2 = new Outer
val o2i = new o2.Inner
val v = new Visitor(o1)

o2i.visit(v)

Here the Outer of v is o1, but the Outer of this (o2i) is o2.

If what you are asking is how to enforce the types so that it becomes so, this might help:

class Outer {
   self => 
   class Inner {
      def visit(v:Visitor[self.type]) = v.visitInner(this)
   }
}

class Visitor[T <: Outer](val o:T) {
    def visitInner(i:o.Inner) = { println("foo") } 
}

However, type inference won't help you if you go this route. You'll have to be explicit about the type of any Visitor, like this:

val v = new Visitor[o1.type](o1)

Upvotes: 7

Related Questions