Почему параметры типа не допускаются во вспомогательных конструкторах Scala? - PullRequest
11 голосов
/ 07 сентября 2011

Скажем, я определяю простой 2D точечный класс в Scala и хочу иметь возможность создавать его с различными типами:

class Point(x:Float, y:Float) {
    this(x:Double, y:Double) = this(x.toFloat, y.toFloat)
    this(x:Int, y:Int) = this(x.toFloat, y.toFloat)
    // etc...
}

Я хочу свести это к минимуму, используя шаблон, например:

class Point(x:Float, y:Float) {
    this[T](x:T, y:T) = this(x.toFloat, y.toFloat)
}

Я знаю, что это все равно не сработает, поскольку T может быть типом, для которого toFloat не определен, но я получаю ошибку компилятора:

здесь нельзя указывать параметры типа

Это просто не поддерживается в Scala? Если так, то почему, и есть ли простой способ обойти это?

Ответы [ 2 ]

14 голосов
/ 07 сентября 2011

Конструкторы классов Scala (в отличие от Java) не могут принимать параметры типа, только сам класс. Что касается того, почему Scala сделала этот выбор дизайна, я предполагаю, что главная причина - простота.

Если вам нужен вторичный «конструктор», который является универсальным, то естественным является определение его для объекта-компаньона. Например,

object Point {
  def build[T : Numeric](x: T, y: T) = {
    val n = implicitly[Numeric[T]]
    new Point(n.toFloat(x), n.toFloat(y))
  }
}

class Point(val x:Float, val y:Float)

val p = Point.build(1, 2) // Companion object's builder
p.x + p.y

Здесь я использовал класс типов Numeric, чтобы получить общий метод toFloat.

3 голосов
/ 07 сентября 2011

Я играл с этим некоторое время, получая "close" как ...

class Point(x:Float, y:Float) {
  def this[T <: Any { def toFloat: Float }](x:T, y:T) = this(x.toFloat, y.toFloat)
}

... что приводит к "error: параметры типа здесь не разрешены" (так же, как в посте)и тогда я понял ...

Если бы инициализатор мог принимать параметры типа, это было бы неоднозначно с параметрами класса, если таковые имеются. Не то, чтобы это не могло работать в спецификации языка ... но это, по крайней мере, более сложный случай.Также могут быть проблемы с совместимостью Java.

Представьте себе:

class Foo[T](x: T) {
   def this[X](z: X) = ...
}
new Foo[Int](42) // T is Int? X is ...? Or ...?

Лично я хотел бы, чтобы Scala следовал шаблону, подобному Eiffel (только именованные конструкторы или "фабричные методы"), но, увы, этоне будет Scala.

Удачного кодирования.

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