so, here's a bit of a contrived example:
trait MyTrait {
type T <: MyTrait
val listOfT:List[T]
def getFirst:T
//def getOne:T = if( listOfT.length > 0 ) { getFirst } else { this }
}
class MyClass extends MyTrait {
type T = MyClass
override val listOfT:List[T] = List[MyClass](this)
override def getFirst:T = listOfT.head
}
The question sort of has two parts:
Is there some other way to do this where the return types in MyClass could just be "MyClass" instead of having to specify "type T = MyClass" ? Basically I want to be able to add this trait to a class without really having to have the subclass change its implementation significantly or think about the type system... to just return members of itself, and have the trait accept anything as long as it is covariant on the subtype. Does this even make sense?
in MyTrait, if uncommented, getOne method will give an error "type mismatch:" found : MyTrait.this.type (with underlying type MyTrait) required: MyTrait.this.T
If I were to change the return type to this.type, I'd get the opposite found/required type mismatch. Either return value actually has the same type (and is actually the same object).
What's the correct way to handle these kinds of situations?
Is this what you want?
trait MyTrait[T <: MyTrait[T]] { self: T =>
val listOfT: List[T]
def getFirst: T
def getOne: T = if (listOfT.length > 0) getFirst else self
}
class MyClass extends MyTrait[MyClass] {
override val listOfT: List[MyClass] = List[MyClass](this)
override def getFirst: MyClass = listOfT.head
}
It gets rid of type T = MyClass (allowing you to just put MyClass in a return type) and fixes the compile error in the definition of getOne.
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