如何引用参数化方法?

时间:2016-04-11 17:12:07

标签: scala

这是一个代码结构:

trait Foo[T <: Foo[_]] {
  def makeACopy[T](attr01_p: Option[String], ...): T
  ...
}

case class Bar extend Foo[Bar] {
  def makeACopy[Bar](attr01_p: Option[String], ...): org.myapp.domain.model.Bar = copy(attr01 = attr01_p, ...)
  ...
}

现在,另一个类中的方法需要引用makeACopy方法。

class Qux(...){
  ...
  private def myMethod[T <: Foo](id: Long, getter: Long => Option[T], ...): Option[T] = {
    val b = getter(id)
    b match {
      case Some(bar) => bar.makeACopy[T](...) // <== It isn't right
      case None => ...
  }
}

虽然我已经将参数指定为Foo的子类型并且Intellij IDEA没有抱怨该行,但是我得到了一个用于调用makeACopy方法的符合错误:

value makeACopy is not a member of type parameter T 

为什么呢?以及如何解决?

另外,我不确定为什么我必须在Bar中为makeACopy的返回数据类型提供完整路径。否则,IDE将抱怨返回的类型不匹配。

1 个答案:

答案 0 :(得分:1)

您正在定义名为T两个单独的类型参数,并且只有其中一个作为Foo的子类:

trait Foo[T <: Foo[_]] { // defining T once
  // that's another definition of a whole different T:
  def makeACopy[T](attr01_p: Option[String], ...): T
  ...
}

在具有类型参数T的特征(或类)中定义的方法不应再次声明T,因此您可能希望将其更改为:

trait Foo[T <: Foo[_]] {
  // T used as return value is the one defined in trait:
  def makeACopy(attr01_p: Option[String], ...): T
  ... 
}

然后,无论您何时呼叫/覆盖makeACopy,您都不需要指定类型,您在创建/扩展Foo时已经做过,例如:

case class Bar extend Foo[Bar] {
  def makeACopy(attr01_p: Option[String], ...): Bar = copy(attr01 = attr01_p, ...)
  ...
}