代码之家  ›  专栏  ›  技术社区  ›  davidrpugh

当性状的类型参数出现在不变位置时,如何使其变位?

  •  2
  • davidrpugh  · 技术社区  · 6 年前

    我想在它的类型参数中使下面的特征变位。

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

    上述解决方案的问题在于scala标准库中的问题 Ordering 在其类型参数中是不变的。这 SO 波斯特讨论了为什么会这样。

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

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

    第二个是使用 implicit .

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

    这两个都是编译的,但我不理解权衡。这些方法中的一种更普遍吗?我应该用第三种方法来代替吗?

    1 回复  |  直到 6 年前
        1
  •  3
  •   slouc    6 年前

    当您试图绕过您所遇到的问题(方法或函数的返回类型是一个逆变参数)时,第一个解决方案被认为是最佳实践。

    第二个解决方案称为 广义类型约束 当您希望在没有编译器“适合它们”的情况下推断正确的类型时,它非常有用。例如,如果你

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

    你试图把它称为

    foo(42, "something")
    

    编译器会推断 A 成为 Any 因为这样整件事就适合了;打字 B ,这是一个 String ,实际上是 . 使用GTC:

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

    编译器将从您的参数推断它们为 Int 分别。只有在检查完GTC之后,才能进行扩展,因为参数类型已经被推断出来了。因此编译将失败,因为字符串不是int的子类型。

    只要你明确地定义了你的A和B,并且你总是会这样做(因为没有什么可以推断的),你的第一个解决方案就是好的。不需要牵连。