2012-04-23 14 views
5

は、私たちが持って考えてみましょう:関数の引数:引数として上限クラスと親クラス?

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

これら二つの関数宣言の違いです:

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

def launch(fo: FlyingObject) 

宣言のどのタイプを使用する際にグレートはいくつかの例になります。 ..

[UPDATE]

もう1つの大きな例と説明はthereです。これは、派生クラスの代わりに上限をパラメータとして使用する必要がある場合の別の例です。

答えて

7

FlyingObjectよりも具体的なTを持つと便利な場合があります。おそらくあなたはメソッドを持っていると想像してください。

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

これは、変更された名前を持つFlyingObjectのコピーを返します。これにより、このコードは型チェックされません:

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

modifyNameはRocketではなくFlyingObjectを返します。代わりに:ロケットが渡されているものであるとき

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

はロケットを返します

+0

つまり、戻り値の型がT型の場合は特に重要です。 –

+2

@LuigiPlinge:型シグネチャ内の他の場所で使用されている可能性があります。あなたは 'def [T <:FlyingObject](1:T、two:T)を比較することもできます。 – stew

4

答えを@stewに加えて、型クラスを使用するときに上限が役に立つかもしれません。たとえば、 は、2つの飛行オブジェクトと、他のオブジェクトとの衝突を管理する方法を定義するcolliderオブジェクトを取るメソッドが必要であるとします。もちろん、小惑星 - 小惑星の衝突は、宇宙船 - 小惑星の衝突(古典的な教科書の例)と同じではありません。

あなたはこのような方法を記述することができます。そして、コンパイラはあなたのための正しいColliderを提供します

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

。代わりにあなたが書いた場合:

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

をあなたは書くことと(二重派遣問題を)維持するためには本当に難しいだろう衝突を管理するためにObect指向の機能に依存する必要があります。

+0

@stew .. + 1の答え – PrimosK

関連する問題