假设我在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中是否不受支持?如果是这样,为什么,有什么简单的方法可以解决这个问题吗?
答案 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。
快乐的编码。