Scala List地图功能的差异

时间:2018-12-07 08:52:52

标签: scala function covariance contravariance generic-variance

我有一个困扰我的问题。 Scala中的列表是协变(List[+A]

假设我们有以下课程:

class A  
class B extends A

map的{​​{1}}函数采用函数List[B]

但是我也可以使用f: B => C 这是f: A => C的子类
这完全有道理。

我目前感到困惑的是 f: B => C函数应仅接受原始函数的超类的函数(因为函数的自变量互斥),不适用于我给出的示例。

我知道我的逻辑有问题,我想启发一下。

2 个答案:

答案 0 :(得分:3)

您的错误在于假设gcpStorageManager = new GcpStorageManager() { @Override protected Storage getStorageConnection(...) { return mockedStorage; } } 仅应接受属于map(f: A => C)的超类的函数。

实际上,A => C将接受map的子类中的任何函数。

在Scala中,函数参数始终可以是所需类型的子类。

A => CA的协方差仅告诉您,只要需要List[A],只要List[A],就可以提供List[B]

或者用简单的话来说:B <: A可以被视为List[B]的子类。

我整理了一个小例子来解释这两种行为:

List[A]

Try it out!

我希望这会有所帮助。

答案 1 :(得分:0)

您已经怀疑,您在这里混淆了一些事情。

一方面,您有一个List[+A],它告诉我们有关List[A]和{{1} }}。如您所知,List[B]A中是协变的事实仅表示BList时的情况。

另一方面,A公开了方法List[B] <: List[A]来更改其“内容”。此方法实际上并不关心B <: A,而仅关心List,因此map的方差在这里无关紧要。让您感到困惑的是,确实有一些子类型需要考虑:List[A]接受一个参数(在这种情况下为A,但实际上并不相关),并且像往常一样使用方法和函数,您始终可以将其参数替换为其子类型的任何内容。在您的特定情况下,只要List,任何map都可以。这里重要的方差是A => C,而不是AcceptedType