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