如何在设计业务应用程序时使用协方差和反方差?

时间:2011-03-11 19:38:49

标签: scala covariance contravariance

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

2 个答案:

答案 0 :(得分:23)

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

trait Function1[-T1, +R]

参数的逆变(-)和返回类型的协变(+)。

为什么?

想象一下,你有这些课程:

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

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

如果您的方法采用Doctor => Enemy函数作为参数;那么可以提供TimeLord => Enemy的实例。它仍然会接受Doctor的实例。

所以TimeLord => EnemyDoctor => Enemy子类,因为TimeLordDoctor超类,它是<该参数中的strong> contravariant 。

同样,当你需要一个函数返回一些Dalek时,返回Enemy的函数是有效的,因为Dalek是一个Enemy

因此Doctor => DalekDoctor => Enemy子类,因为DalekEnemy子类,它是<该参数中的strong> covariant 。

答案 1 :(得分:9)

基本上你想要使用parametric polymorphism (泛型)和继承的任何地方,你可能最终都想要declaration site variance ({{1 } / +use site variance (通配符),或更有可能,两者都有。

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

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