2010-05-14 79 views
4

所以我現在正在學習Scala,我正在嘗試創建一個矢量空間爲3(x,y,z座標)的抽象矢量類。我試圖添加兩個這些載體連同下面的代碼:Scala中的類型參數化


package math 

class Vector3[T](ax:T,ay:T,az:T) { 
    def x = ax 
    def y = ay 
    def z = az 
    override def toString = "<"+x+", "+y+", "+z+">" 
    def add(that: Vector3[T]) = new Vector3(x+that.x, y+that.y, z+that.z) 
} 

的問題是我不斷收到此錯誤:

error: type mismatch;
found : T
required: String
def add(that: Vector3[T]) = new Vector3(x+that.x, y+that.y, z+that.z)

我試着註釋掉「的toString」方法,但似乎沒有任何效果。誰能告訴我我做錯了什麼?

回答

7

使用Scala的2.8,你可寫:

case class Vector3[T: Numeric](val x: T, val y: T, val z: T) { 
    override def toString = "(%s, %s, %s)" format (x, y, z) 

    def add(that: Vector3[T]) = new Vector3(
    plus(x, that.x), 
    plus(y, that.y), 
    plus(z, that.z) 
) 

    private def plus(x: T, y: T) = implicitly[Numeric[T]] plus (x, y) 
} 

讓我解釋一下。首先,T: Numeric是一個上下文綁定,它隱式地爲您的類提供了一個Numeric[T]實例。

Numeric[T]性狀提供數字類型的操作,

trait Numeric[T] extends Ordering[T] { 
    def plus(x: T, y: T): T 
    def minus(x: T, y: T): T 
    def times(x: T, y: T): T 
    def negate(x: T): T 
    // other operations omitted 
} 

表達implicitly[Numeric[T]]檢索,使得可以執行操作,諸如plus您的具體參數的x,y和z,如在示出的該隱式上下文上面的私有方法。

現在,您可以構建和add不同的Vector3實例如用Int的和Double的:

scala> Vector3(1,2,3) add Vector3(4,5,6)         
res1: Vector3[Int] = (5, 7, 9) 

scala> Vector3(1.1, 2.2, 3.3) add Vector3(4.4, 5.5, 6.6)      
res2: Vector3[Double] = (5.5, 7.7, 9.899999999999999) 

側面說明:這是可以使用隱式轉換爲數值轉換爲Numeric[T].Ops情況下,使得下面可以代替書面:

def add(that: Vector3[T]) = new Vector3(x + that.x, y + that.y, z + that.z) 

我特意選擇不使用這些隱式轉換,因爲他們(可能)招致一些績效通過創建臨時包裝對象來懲罰。實際的性能影響取決於JVM(例如,爲了避免堆上的實際對象分配,其支持逃逸分析的程度)。使用上下文綁定和implicitly避免了這種潛在的開銷...以一些冗長的代價。

6

問題是T。它的類型爲Any,但Any沒有+運算符。關於String的錯誤是有點小姐領先。所以你將不得不定義一個類型的最小範圍。

+1

在2.8這是'OPS',或者我被告知。我不知道2.7中該做什麼,但我是斯卡拉新手。 – erisco 2010-05-14 19:38:50

8

您沒有約束類型參數T,因此編譯器回退爲+的解釋爲字符串連接。

3

無論是從@sblundy和@Randall舒爾茨的答案是正確的,當然,但如果你需要了解如何約束T接一些更具體的建議怎麼樣:

class Vector3[T <% Double](ax:T,ay:T,az:T) { 
... 
}