Update: Clarified and expanded, since the original question was simplified too far
I need a pair of traits, each of which refers to the other such that parent and child classes must relate to each other.
trait Parent [C <: Child] {
def foo(c: C)
}
trait Child [P <: Parent] {
def parent: P = ...
def bar = parent.foo(this)
}
Such that implementing classes must come in pairs:
class ActualParent extends Parent [ActualChild] {
def foo(c: ActualChild) = ...
}
class ActualChild extends Child [ActualParent] {
}
Unfortunately, the compiler doesn't like these traits because the generic types aren't complete. Instead of C <: Child
it needs to say C <: Child[
something]
. Leaving them unspecified doesn't work either:
trait Parent [C <: Child[_]] {
def foo(c: C)
}
trait Child [P <: Parent[_]] {
def parent: P = ...
def bar = parent.foo(this)
}
It now complains on the parent.foo(this)
line, because it doesn't know that this
is of the correct type. The type of parent
needs to be Parent[this.type]
for the call to foo
to have the right types.
I'm thinking there must be a way of referring to an object's own type? Or to a type that's required to be itself?
Update: Further to @Daniel's answer, I tried using an abstract type member within the child to state the generic types of the parent type like this:
trait Parent [C <: Child] {
def foo(c: C)
}
trait Child {
type P <: Parent[this.type]
def parent: P = ...
def bar = parent.foo(this)
}
This isn't working when I try to implement it:
class ActualParent extends Parent [ActualChild] {
def foo(c: ActualChild) = ...
}
class ActualChild extends Child {
type P = ActualParent
}
Gives the following error:
overriding type Parent in trait Child with bounds >: Nothing <: Parent[ActualChild.this.type]
type Parent has incompatible type
What does that mean?
You can use the approach given in http://programming-scala.labs.oreilly.com/ch13.html:
abstract class ParentChildPair {
type C <: Child
type P <: Parent
trait Child {self: C =>
def parent: P
}
trait Parent {self: P =>
def child: C
}
}
class ActualParentChildPair1 {
type C = Child1
type P = Parent1
class Child1 extends Child {...}
class Parent1 extends Parent {...}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With