My scenario is like:
trait A {
type B
def foo(b: B)
}
trait C[D <: A] {
val d: D
def createB(): D#B
def bar() {
d.foo(createB)
}
}
In REPL, it complains
<console>:24: error: type mismatch;
found : D#B
required: C.this.d.B
a.bar(createB())
What's wrong with this ? And (if possible at all) how to correct this code ?
D#Bis a type projection, and is not the same asd.B. You have a type mismatch because infoo,Bactually meantthis.B, which as said is not the same asD#B(the latter being more general). Informally, you can think ofD#Bas representing any possible type that the abstract typeBcan take for any instance ofD, whiled.Bis the type ofBfor the specific instanced.See What does the `#` operator mean in Scala? and What is meant by Scala's path-dependent types? for some context.
One way to make it compile it is by changing
createB's return type tod.B:However in many cases such a solution is too restrictive because you are tied to the specific instance
d, which might not be what you had in mind. Another solution is then to replace the abstract type with a type parameter (though it is more verbose):