2012-04-23 42 views
5

考慮,我們有:函數參數:上界vs父類作爲參數?

abstract class FlyingObject; 
case class Rocket(name: String) extends FlyingObject; 

就是這兩個函數聲明之間的區別:

def launch[T <: FlyingObject](fo: T) 

def launch(fo: FlyingObject) 

大是一些例子時使用聲明的哪種類型。 ..

[UPDATE]

另一個很好的例子和說明,可以發現there。這是您應該使用上限而不是派生類作爲參數的另一個示例。

回答

7

這可能是有用的一件T比FlyingObject更具體。也許想象你有一個方法

def modifyName(fo: FlyingObject, newName: String): FlyingObject = fo.copy(name=newName) 

它返回FlyingObject的一份和修改後的名稱。這使得該代碼沒有進行類型檢查:

val newRocket: Rocket = modifyName(oldRocket, "new name") 

由於modifyName返回FlyingObject不是火箭。而不是:

def modifyName[T <: FlyingObject](fo: T, newName: String): T = fo.copy(name=newName) 

將返回火箭的時候火箭就是在通過

+0

換句話說,這事特別是當返回類型爲類型T. – 2012-04-23 17:18:28

+2

@LuigiPlinge:也許當它用於其他地方的類型簽名。因爲你可能想'def比較[T <:FlyingObject](一個:T,two:T)'也 – stew 2012-04-23 17:30:30

4

除了@stew答案,使用類型類時的上限可能是有用的。例如, 假設您需要一種方法,該方法需要兩個飛行物體以及一個定義如何管理與其他物體的碰撞的碰撞物體。當然,小行星 - 小行星碰撞不同於太空船 - 小行星碰撞(古典教科書示例)。

你可以寫這樣的方法爲:

def collide[A <: FlyingObject, B <: FlyingObject] 
    (a: A, b: B)(implicit collider: Collider[A,B]) = collider.apply(a,b) 

編譯器會爲你提供正確的Collider。相反,如果你寫道:

def collide(a: FlyingObject, b: FlyingObject) = a.collide(b) 

你將不得不依靠Obect導向功能來管理,這將是真的很難編寫和維護(雙調度問題)的碰撞。

+0

@stew答案的好處.. +1 – PrimosK 2012-04-23 20:05:11