假设我希望得到以下内容:
abstract class PDF[T, S <: PDF[T, _]] {
def fit(obs: Seq[T], weights: Seq[Double]): S
}
class PDFGaussian(val mu: Double, val Sigma: Double) extends PDF[Double, PDFGaussian] {
def fit(obs: Seq[Double], weights: Seq[Double]): PDFGaussian =
new PDFGaussian(...) // bla bla bla
}
所以,基本上,我想要的是让fit
函数返回其封闭类的实例,这显然必须是PDF[T]
的子类。
但是,我不想使用双参数化PDF[T, S <: PDF[T, _]]
,而是只使用一个类型参数,如下所示:
abstract class PDF[T] {
def fit[S <: PDF[T]](obs: Seq[T], weights: Seq[Double]): S
}
class PDFGaussian(val mu: Double, val Sigma: Double) extends PDF[Double] {
def fit[S <: PDF[_]](obs: Seq[Double], weights: Seq[Double]): S =
new PDFGaussian(...) // bla bla bla
}
但是,如果我这样做,编译器会因为返回PDFGaussian
而不是S
而对我大喊大叫。既然我明显错过了关于scala类型系统的一些重要事实,请你澄清一下我做错了什么,并告诉我如何用一个类型参数做到这一点?
答案 0 :(得分:5)
你的第一个解决方案非常好,恕我直言。但是让我们谈谈这些问题。首先,关于这里有什么问题:
abstract class PDF[T] {
def fit[S <: PDF[T]](obs: Seq[T], weights: Seq[Double]): S
}
class PDFGaussian(val mu: Double, val Sigma: Double) extends PDF[Double] {
def fit[S <: PDF[_]](obs: Seq[Double], weights: Seq[Double]): S =
new PDFGaussian(...) // bla bla bla
}
假设我有
class FooBar extends PDF[Double] { ... }
我做了:
val pdfg = new PDFGaussian(1.0, -1.0)
val foobar = pdfg.fit[FooBar](List(0.5, 0.75), List(4, 2))
所以,我告诉编译器我希望S
为FooBar
,但是你要返回PDFGaussian
!这就是编译器所抱怨的。
那么,如何解决呢?嗯......很难。 :-)怎么样:
abstract class PDF[T] {
type S <: PDF[T]
def fit(obs: Seq[T], weights: Seq[Double]): S
}
class PDFGaussian(val mu: Double, val Sigma: Double) extends PDF[Double] {
type S = PDFGaussian
def fit(obs: Seq[Double], weights: Seq[Double]): S =
new PDFGaussian(...) // bla bla bla
}
它有点冗长,但它使PDF
类型签名更清晰。