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#B
is a type projection, and is not the same asd.B
. You have a type mismatch because infoo
,B
actually meantthis.B
, which as said is not the same asD#B
(the latter being more general). Informally, you can think ofD#B
as representing any possible type that the abstract typeB
can take for any instance ofD
, whiled.B
is the type ofB
for 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):