16

我知道在标准库中使用co-contravariance(例如集合和特征Function)我想知道如何co-以及contravariance在“现实世界”业务应用程序的设计中使用。

4

2 回答 2

24

经典示例是函数,将 Scala 接口用于具有单个参数的函数:

trait Function1[-T1, +R]

对于参数,它是逆变的 (the ) ,对于返回类型是-协变的 (the )。+

为什么?

想象一下你有这些类:

class Timelord { ... }
class Doctor extends Timelord { ... }

class Enemy { ... }
class Dalek extends Enemy { ... }

如果您有一个将函数作为参数的Doctor => Enemy方法;那么可以提供TimeLord => Enemy. 它仍然会接受Doctor.

SoTimeLord => Enemy是 的子类Doctor => Enemy因为TimeLord它是 的超类Doctor它在该参数中是逆变的。

同样,Dalek当您需要返回 a 的函数时,返回 a 的函数是有效的Enemy,因为 a Dalekis-anEnemy

SoDoctor => Dalek是 的子类Doctor => Enemy因为Dalek是 的子类Enemy它在该参数中是协变的。

于 2011-03-11T23:53:00.937 回答
9

基本上在您想要同时使用参数多态性 (泛型)和继承的任何地方,您可能最终都需要声明站点方差 +/ -使用站点方差 (通配符),或者更有可能两者兼而有之。

多态类型通常是相当高级别的抽象,因此虽然您的域对象可能不需要方差注释,但您编写的用于操作域对象的代码可能需要使用方差注释,至少如果您的域对象是继承的一部分层次结构,这似乎非常频繁。

如果您基本上看一下任何库或框架,您会发现经常使用方差注释。如果你正确地抽象了你的“现实世界”应用程序,你可能会编写很多库来支持它,其中关键业务逻辑的一个小核心很好地与所有支持基础设施分离。所有支持基础设施的人也可能会频繁使用方差注释。

于 2011-03-11T23:17:54.210 回答