我知道在标准库中使用co-
和contravariance
(例如集合和特征Function
)我想知道如何使用co-
和contravariance
设计“现实世界”的商业应用程序。
答案 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 => Enemy
是Doctor => Enemy
的子类,因为TimeLord
是Doctor
的超类,它是<该参数中的strong> contravariant 。
同样,当你需要一个函数返回一些Dalek
时,返回Enemy
的函数是有效的,因为Dalek
是一个Enemy
因此Doctor => Dalek
是Doctor => Enemy
的子类,因为Dalek
是Enemy
的子类,它是<该参数中的strong> covariant 。
答案 1 :(得分:9)
基本上你想要使用parametric polymorphism (泛型)和继承的任何地方,你可能最终都想要declaration site variance ({{1 } / +
),use site variance (通配符),或更有可能,两者都有。
多态类型通常是相当高级的抽象,因此虽然您的域对象可能不需要方差注释,但您编写的用于操作域对象的代码可能需要使用方差注释,至少如果您的域对象是继承层次结构的一部分,似乎非常频繁。
如果你看一下基本上任何库或框架,你会发现经常使用方差注释。如果你正确地抽象你的“真实世界”应用程序,你可能会编写大量的库来支持它,一小部分关键业务逻辑核心与所有支持基础架构很好地分离。所有支持基础设施的人也可能经常使用方差注释。