I'd like to be able to do something like this:
trait A {
def f(): ???_THE_EXTENDING CLASS
}
class C extends A {
def f() = self
}
class D extends A {
def f() = new D
}
class Z extends D {
def f() = new Z
}
And the following would not compile, given the above code
class Bad1 extends A {
def f() = "unrelated string"
}
class Bad2 extends A {
def f() = new C // this means that you can't just define a type parameter on
// A like A[T <: A] with f() defined as f: T
}
class Bad3 extends D // f() now doesn't return the correct type
Is there a name for this kind of relationship? And how is it annotated/implemented in Scala?
The following sort of works, as you can see:
scala> trait A {
| def f: this.type
| }
defined trait A
scala> class C extends A {
| def f = this
| }
defined class C
scala> class D extends A {
| def f = new D
| }
<console>:7: error: type mismatch;
found : D
required: D.this.type
def f = new D
^
Is there a way to get around that?
Using the second system, I can do this, which is good up to the definition of class D:
scala> trait A[T <: A[T]] { def f(): T }
defined trait A
// OR
scala> trait A[T <: A[T]] { self: T =>
| def f(): T
| }
scala> class C extends A[C] { def f() = new C }
defined class C
scala> class D extends C
defined class D
scala> (new D).f
res0: C = C@465fadce
I'm afraid there is no possibility to know what is the extended class from the extending class.
The closest to what you'd like to have is something similar to Curiously Recurring Template Pattern (CRTP) well known from C++.
trait A[T <: A[T]] {
def f(): T;
}
class C extends A[C] {
def f() = new C
}
class D extends A[D] {
def f() = new D
}
One thing that you can do, is to return type this.type
:
trait A {
def f(): this.type
}
class C extends A {
def f() = this
}
class D extends A {
def f() = this
}
class Z extends D {
override def f() = this
def x = "x"
}
println((new Z).f().x)
This can be useful for builders.
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