Подклассы и возвращаемые типы - PullRequest
1 голос
/ 22 марта 2011

допустим, я хотел получить что-то вроде следующего:

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, не могли бы вы уточнить, что я делаю неправильно, и показать, как это сделать только с одним параметром типа?

1 Ответ

5 голосов
/ 22 марта 2011

Ваше первое решение довольно хорошее, ИМХО.Но давайте поговорим о вопросах.Во-первых, о том, что здесь не так:

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 чистоту подписи типа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...