考虑一下我们:
abstract class FlyingObject;
case class Rocket(name: String) extends FlyingObject;
这两个函数声明之间有什么区别:
def launch[T <: FlyingObject](fo: T)
和
def launch(fo: FlyingObject)
在使用哪种声明时会有一些例子...
[UPDATE]
可以找到另一个很好的例子和解释there。这是你应该使用上限而不仅仅是派生类作为参数的另一个例子。
答案 0 :(得分:7)
使用比FlyingObject更具体的T可能很有用。也许想象你有一个方法
def modifyName(fo: FlyingObject, newName: String): FlyingObject = fo.copy(name=newName)
返回带有修改名称的FlyingObject的副本。这使得这段代码不是类型检查:
val newRocket: Rocket = modifyName(oldRocket, "new name")
由于modifyName返回的是FlyingObject而不是Rocket。代替:
def modifyName[T <: FlyingObject](fo: T, newName: String): T = fo.copy(name=newName)
当Rocket传入时,将返回Rocket。
答案 1 :(得分: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的功能来管理难以编写和维护的碰撞(双重调度问题)。