当其类型参数出现在不变位置时,如何使特征逆变?

How to make trait contravariant when its type parameter appears in an invariant position?

我想在其类型参数中使以下特征逆变。

trait Preferences[-A] {
  def ordering: Ordering[A]
}

上述解决方案的问题在于,在 Scala 标准库中,Ordering 的类型参数是不变的。这个SOpost讨论了为什么会这样

我已经为我的问题制定了两个解决方案。第一个解决方案是使参数A和上限

trait Preferences[-A] {
  def ordering[B <: A]: Ordering[B]
}

第二种是使用implicit.

trait Preferences[-A] {
  def ordering(implicit ev: B <:< A): Ordering[B]
}

这两个都可以编译,但我不明白权衡取舍。这些方法中的一种更通用吗?我应该改用第三种方法吗?

在尝试解决您遇到的问题时,您的第一个解决方案被认为是最佳实践(具有逆变参数作为 return 类型的方法或函数)。

第二种解决方案称为广义类型约束,当您想在没有编译器的情况下推断正确的类型时非常有用"fit them"。例如,如果您有

def foo[A, B <: A](a: A, b: B): Whatever = ???

并且您尝试将其调用为

foo(42, "something")

编译器会推断 AAny,因为这样整个事情就适合了; B 类型是 String,确实是 Any 的子类型。使用 GTC:

def foo[A, B](a: A, b: B)(implicit ev: B <:< A)

编译器将从您的参数中推断出它们分别为 IntString。只有在那之后它才会检查 GTC,这里不能进行扩展,因为已经推断出参数类型。所以编译会失败,因为 String 不是 Int 的子类型。

只要您明确定义了 A 和 B,而且您总是会这样做(因为没有什么可以从中推断出它们),您的第一个解决方案就可以了。不需要隐式。