Reputation: 11512
Here's the behavior I'm trying to achieve:
trait PathLike {
val given: String
def factory[T <: PathLike]( g: String ):T
def +[T <: PathLike]( part: String ): T = factory(this.given+"/"+part)
}
case class Path( given: String ) extends PathLike {
def factory[Path]( g: String ) = Path(g)
}
case class NonRelativePath( given: String ) extends PathLike {
def factory[NonRelativePath]( g: String ) = NonRelativePath(g)
}
I have other functions in PathLike that use + so simply moving the + function into each of the specific case classes doesn't seem like a good option.
Currently the compiler complains:
type mismatch; found : com.foo.Path required: Path Path.scala
type mismatch; found : com.foo.NonRelativePath required: NonRelativePath Path.scala
Why is it complaining as it has Path/NonRelativePath respectively? How can I construct a properly typed child of PathLike from within PathLike?
Upvotes: 1
Views: 73
Reputation: 38045
You should use a trait
type parameter instead of method
type parameter since it should be applied on instance creation instead of method application.
trait PathLike[T <: PathLike] {
val given: String
def factory( g: String ):T
def +( part: String ): T = factory(this.given+"/"+part)
}
case class Path( given: String ) extends PathLike[Path] {
def factory( g: String ) = Path(g)
}
case class NonRelativePath( given: String ) extends PathLike[NonRelativePath] {
def factory( g: String ) = NonRelativePath(g)
}
Using def factory[Path]( g: String ) =
you are creating a new name for methods type parameter. See these answers for additional information about type shadowing: 1, 2, 3.
Upvotes: 2
Reputation: 2583
Explicitly add the return type in the definition.
def factory[Path]( g: String ): Path = Path(g)
Upvotes: 0