简体   繁体   中英

How can I have a typed (specific) factory in a base trait in Scala?

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?

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 .

在定义中明确添加返回类型。

def factory[Path]( g: String ): Path = Path(g)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM