为什么Scala辅助构造函数中不允许使用类型参数?

时间:2011-09-06 22:45:34

标签: templates scala constructor

假设我在Scala中定义了一个简单的2D点类,我希望能够用各种类型构建它:

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 个答案:

答案 0 :(得分:14)

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方法。

答案 1 :(得分:3)

我玩了一段时间,和......一样“接近”......

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

...导致“错误:此处不允许输入类型参数”(就像帖子一样)然后我意识到......

如果初始化程序可以采用类型参数,那么类参数(如果有的话)将是不明确的。不是无法在语言规范中处理 。 ..但至少它是一个更复杂的案例。可能还存在Java互操作性问题。

想象:

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

我个人希望Scala遵循类似埃菲尔的模式(仅命名构造函数或“工厂方法”),但唉,这不会是Scala。

快乐的编码。