子类和返回类型 [英] Subclasses and return types

查看:117
本文介绍了子类和返回类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我想拥有类似以下内容的东西:

let's say I wanted to have something like the following:

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, _]],我宁愿只使用一个类型参数,如下所示:

So, basically, what I want is to have the fit function to return an instance of the type of its enclosing class which obviously must be a subclass of PDF[T]. However, instead of having to use the double parameterization PDF[T, S <: PDF[T, _]] I'd rather go with only one type parameter like so:

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的类型系统的一些重要事实,请您说明一下我做错了什么,并向我展示如何仅使用一个类型参数来做到这一点?

If I do this, however, the compiler yells at me for returning PDFGaussian instead of S. Since I'm obviously missing some important fact about scala's type system here could you please clarify what I'm doing wrong and show me how to do it with only one type parameter?

推荐答案

您的第一个解决方案很好,恕我直言.但是,让我们谈谈这些问题.首先,关于这里出了什么问题:

Your first solution is pretty good, IMHO. But let's talk about the questions. First, about what is wrong here:

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!这就是编译器所抱怨的.

So, I'm telling the compiler that I want S to be FooBar, but you are returning PDFGaussian! That's what the compiler is complaining about.

那么,如何解决呢?好吧...很难. :-)怎么样:

So, how to solve it? Well... tough. :-) How about this:

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类型签名更整洁.

It's a bit more verbose, but it keeps PDF type signature cleaner.

这篇关于子类和返回类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆