如何确定类型参数的方差?

发布于 2024-10-21 06:14:13 字数 234 浏览 2 评论 0原文

受到 Scala 中协变和逆变的真实示例< /a> 我认为更好的问题是:

在设计库时,在确定类型参数应该是协变还是逆变时,您是否应该问自己一组特定的问题?或者你应该让一切保持不变,然后根据需要进行更改?

Inspired by Real-world examples of co- and contravariance in Scala I thought a better question would be:

When designing a library, are there a specific set of questions you should ask yourself when determining whether a type parameter should be covariant or contravariant? Or should you make everything invariant and then change as needed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

み青杉依旧 2024-10-28 06:14:13

嗯,很简单,有道理吗?想想里氏替换。

协方差

如果 A <: B,则在需要 C[B] 的地方传递 C[A] 是否有意义?如果是这样,请将其设为C[+T]。经典的例子是不可变的 List,其中 List[A] 可以传递给任何需要 List[B] 的东西,假设 AB 的子类型。

两个反例:

可变序列是不变的,因为否则可能会出现类型安全违规(事实上,Java 的协变体 Array 很容易受到此类问题的影响,这就是为什么它在 Scala 中是不变的)。

不可变的 Set 是不变的,尽管它的方法与不可变的 Seq 的方法非常相似。区别在于contains,它在集合上是类型化的,而在序列上是非类型化的(即接受Any)。因此,即使可以使其具有协变性,但对特定方法增加类型安全性的渴望导致选择不变性而不是协变性。

反方差

如果 A <: B,则在需要 C[A] 的地方传递 C[B] 是否有意义?如果是这样,请将其设为C[-T]。典型的例子是Ordering。虽然一些不相关的技术问题阻止了 Ordering 逆变,但直观的是,任何可以订购 A 超类的东西也可以订购 A.由此可见,Ordering[B] 对所有 B 类型(A 的超类型)元素进行排序,可以传递给需要 B 的元素。代码>排序[A]。

虽然 Scala 的 Ordering 不是逆变,但 Scalaz 的 < a href="http://scalaz.googlecode.com/svn/continuous/latest/browse.sxr/scalaz/Order.scala.html" rel="noreferrer">顺序 正如预期的那样是逆变的。 Scalaz 的另一个示例是其Equal特征。

混合方差?

Scala 中最明显的混合方差示例是 Function1(以及 2、3 等)。它接收的参数是逆变的,返回的参数是协变的。但请注意,Function1 用于很多闭包,并且在很多地方都使用了闭包,而这些地方通常是 Java 使用(或将使用)单一抽象方法类的地方。

因此,如果您遇到 SAM 类适用的情况,那么这很可能是混合逆变和协方差的地方。

Well, simple, does it make sense? Think of Liskov substitution.

Co-variance

If A <: B, does it make sense to pass a C[A] where a C[B] is expected? If so, make it C[+T]. The classic example is the immutable List, where a List[A] can be passed to anything expecting a List[B], assuming A is a subtype of B.

Two counter examples:

Mutable sequences are invariant, because it is possible to have type safety violations otherwise (in fact, Java's co-variant Array is vulnerable to just such things, which is why it is invariant in Scala).

Immutable Set is invariant, even though its methods are very similar to those of an immutable Seq. The difference lies with contains, which is typed on sets and untyped (ie, accept Any) on sequences. So, even though it would otherwise be possible to make it co-variant, the desire for an increased type safety on a particular method led to a choice of invariance over co-variance.

Contra-variance

If A <: B, does it make sense to pass a C[B] where a C[A] is expected? If so, make it C[-T]. The classic would-be example is Ordering. While some unrelated technical problems prevent Ordering from being contra-variant, it is intuitive that anything that can order a super-class of A can also order A. It follows that Ordering[B], which orders all elements of type B, a supertype of A, can be passed to something expecting an Ordering[A].

While Scala's Ordering is not contra-variant, Scalaz's Order is contra-variant as expected. Another example from Scalaz is its Equal trait.

Mixed Variance?

The most visible example of mixed variance in Scala is Function1 (and 2, 3, etc). It is contra-variant in the parameter it receives, and co-variant in what it returns. Note, though, that Function1 is what is used for a lot of closures, and closures are used in a lot of places, and these places are usually where Java uses (or would use) Single Abstract Method classes.

So, if you have a situation where a SAM class applies, that's likely a place for mixed contra-variance and co-variance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文