这是一个代码结构:
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将抱怨返回的类型不匹配。
答案 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, ...)
...
}