我试图理解编译器如何检查类型参数的位置是协变还是逆变。
据我所知,如果type参数是用+来注释的,那就是协变注释,那么任何方法都不能有一个用class / trait类型参数输入的输入参数。
例如,bar
不能包含T
类型的参数。
class Foo[+T] {
def bar(param: T): Unit =
println("Hello foo bar")
}
因为bar()
参数的位置被认为是负数,这意味着该位置的任何类型参数都处于逆变位置。
我很好奇Scala编译器如何能够找到类/特征中的每个位置是正面的,负面的还是中性的。似乎存在一些规则,比如在某些条件下翻转其位置但无法清楚地理解它。
另外,如果可能的话,我想知道如何定义这些规则。例如,似乎在具有协变注释的类中定义的方法的参数(如bar()
类中的Foo
方法)应该具有逆变类类型。为什么?
答案 0 :(得分:2)
我很好奇Scala编译器如何找到它中的每个位置 阶级/特质是积极的,消极的或中立的。似乎那里 存在一些规则,比如在某些条件下翻转其位置但是 无法清楚地理解它。
Scala compiler有一个称为解析器的阶段(与大多数编译器一样),它遍历文本并解析出令牌。其中一个令牌称为方差。如果我们深入研究细节,那么有一个名为Parsers.typeParamClauseOpt
的方法,它负责解析类型参数子句。与您的问题相关的部分是:
def typeParam(ms: Modifiers): TypeDef = {
var mods = ms | Flags.PARAM
val start = in.offset
if (owner.isTypeName && isIdent) {
if (in.name == raw.PLUS) {
in.nextToken()
mods |= Flags.COVARIANT
} else if (in.name == raw.MINUS) {
in.nextToken()
mods |= Flags.CONTRAVARIANT
}
}
解析器在类型参数签名中查找+
和-
符号,并创建一个名为TypeDef
的类,该类描述了它的协变性,逆变性或不变性的类型和状态
另外,如果可能的话,我想知道如何定义这些规则。
方差规则具有普遍性,它们源于一个名为Category Theory的数学分支。更具体地说,它们来自Covariant and Contravariant Functors和两者之间的组合。如果您想了解有关这些规则的更多信息,那就是我要走的路。
此外,Scala编译器中有一个名为Variance
的类,如果您想深入了解,它看起来像是方差规则的辅助类。