函数参数:上限vs父类作为参数?

时间:2012-04-23 16:49:50

标签: scala types parameters function-declaration

考虑一下我们:

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

这两个函数声明之间有什么区别:

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

def launch(fo: FlyingObject)

在使用哪种声明时会有一些例子...

[UPDATE]

可以找到另一个很好的例子和解释there。这是你应该使用上限而不仅仅是派生类作为参数的另一个例子。

2 个答案:

答案 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的功能来管理难以编写和维护的碰撞(双重调度问题)。