我知道在标准库中使用co-
和contravariance
(例如集合和特征Function
)我想知道如何co-
以及contravariance
在“现实世界”业务应用程序的设计中使用。
2 回答
经典示例是函数,将 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 Dalek
is-anEnemy
SoDoctor => Dalek
是 的子类,Doctor => Enemy
因为Dalek
是 的子类,Enemy
它在该参数中是协变的。
基本上在您想要同时使用参数多态性 (泛型)和继承的任何地方,您可能最终都需要声明站点方差 (+
/ -
),使用站点方差 (通配符),或者更有可能两者兼而有之。
多态类型通常是相当高级别的抽象,因此虽然您的域对象可能不需要方差注释,但您编写的用于操作域对象的代码可能需要使用方差注释,至少如果您的域对象是继承的一部分层次结构,这似乎非常频繁。
如果您基本上看一下任何库或框架,您会发现经常使用方差注释。如果你正确地抽象了你的“现实世界”应用程序,你可能会编写很多库来支持它,其中关键业务逻辑的一个小核心很好地与所有支持基础设施分离。所有支持基础设施的人也可能会频繁使用方差注释。