2011-09-06 84 views
11

说我定义Scala中的一个简单的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一个类型,但是编译器错误我得到的是:

no type parameters allowed here

这只是unsupp在斯卡拉砸了吗?如果是这样,为什么,还有什么简单的方法来解决这个问题?

回答

14

Scala的类构造函数(不像Java的)不能接受类型参数,只有类本身可以。至于斯卡拉为什么选择这种设计,我认为主要原因是简单。

如果你想要一个通用的辅助“构建器”方法,自然要做的就是在辅助对象上定义它。例如,

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

如果你调用这个方法'apply',那么你可以写'val p = Point(1,2)',不是? –

+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 ...? 

个人而言,我希望斯卡拉随后的埃菲尔铁塔状的图案(仅命名的构造函数或“工厂方法”),但很可惜,这不会是斯卡拉。

快乐编码。

相关问题