Reputation: 29463
Suppose I have a trait SomeTrait
with an unimplemented method func
. This method is going to return something that extends SomeTrait
. In other words, I've got something like the following:
trait SomeTrait
{
def func(x: Int): SomeTrait
}
Now, I implement a class ExtensionClass
that extends SomeTrait
and it turns out that I in fact want the implementation of func
in this class to return an object of type ExtensionClass
:
class ExtensionClass(val param: String) extends SomeTrait
{
override def func(x: Int): SomeTrait = return new ExtensionClass("test")
// ExtensionClass also defines another method not specified in SomeTrait
def anotherMethod: String = return param ++ "!"
}
So far, everything above works nicely. The problem arises if I want to call anotherMethod
on the object returned by func
like so:
val extension = new ExtensionClass("hello")
extension.func(5).anotherMethod
The type system only recognises that the object given by extension.func(5)
is of type SomeTrait
and so anotherMethod
is not visible. This brings us to my question:
Question:
Is it possible to make the above work without having to explicitly cast/pattern match on the result of func
? For instance, can I update the type signature of func
in SomeTrait
so that some sort of type inference can happen? Any help will be appreciated.
Upvotes: 2
Views: 1108
Reputation: 144126
You can add a generic parameter:
trait SomeTrait[T <: SomeTrait[T]] {
def func(x: Int): T
}
class ExtensionClass(val param: String) extends SomeTrait[ExtensionClass] {
def func(x: Int) = new ExtensionClass("test")
def anotherMethod: String = param ++ "!"
}
alternatively you could add an abstract type member:
trait SomeTrait {
type T <: SomeTrait
def func(x: Int): T
}
class ExtensionClass(val s: String) extends SomeTrait {
type T = ExtensionClass
def func(x: Int) = new ExtensionClass("test")
def anotherMethod: String = s ++ "!"
}
Upvotes: 6