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 as dB
. You have a type mismatch because in foo
, B
actually meant this.B
, which as said is not the same as D#B
(the latter being more general). Informally, you can think of D#B
as representing any possible type that the abstract type B
can take for any instance of D
, while dB
is the type of B
for the specific instance d
.
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 to dB
:
def createB(): d.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):
trait A[B] {
def foo(b: B)
}
trait C[B, D <: A[B]] {
val d: D
def createB(): B
def bar() {
d.foo(createB)
}
}
Update given this answer I'm not sure whether this should be considered a bug or not
This is a bug: SI-4377 . An explicit type ascription yields
trait C[D <: A] {
val d: D
def createB(): D#B
def bar() {
(d:D).foo(createB)
// [error] found : D#B
// [error] required: _3.B where val _3: D
}
}
which looks like the implementation leaking. There's a workaround which involves casting to an intersection type (dangerous, casting is wrong etc; see my other answer here )
trait A {
type B
def foo(b: B)
}
case object A {
type is[A0 <: A] = A0 {
type B = A0#B
}
def is[A0 <: A](a: A0): is[A0] = a.asInstanceOf[is[A0]]
}
trait C[D <: A] {
val d: D
def createB(): D#B
def bar() {
A.is(d).foo(createB) // use it here!
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.