fot*_*ton 1 scala covariance subtype
假设我想要有以下内容:
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
}
Run Code Online (Sandbox Code Playgroud)
所以,基本上,我想要的是让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
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我这样做,编译器会因为返回PDFGaussian而对我大喊大叫而不是S.既然我明显错过了关于scala类型系统的一些重要事实,请你澄清一下我做错了什么,并告诉我如何用一个类型参数做到这一点?
你的第一个解决方案非常好,恕我直言.但是让我们谈谈这些问题.首先,关于这里有什么问题:
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
}
Run Code Online (Sandbox Code Playgroud)
让我说我有
class FooBar extends PDF[Double] { ... }
Run Code Online (Sandbox Code Playgroud)
我这样做:
val pdfg = new PDFGaussian(1.0, -1.0)
val foobar = pdfg.fit[FooBar](List(0.5, 0.75), List(4, 2))
Run Code Online (Sandbox Code Playgroud)
所以,我告诉编译器我想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
}
Run Code Online (Sandbox Code Playgroud)
它有点冗长,但它保持了PDF类型签名更清晰.
| 归档时间: |
|
| 查看次数: |
2108 次 |
| 最近记录: |