2011-09-06 113 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 ...? 

個人而言,我希望斯卡拉隨後的埃菲爾鐵塔狀的圖案(僅命名的構造函數或「工廠方法」),但很可惜,這不會是斯卡拉。

快樂編碼。

相關問題