是否可以在Scala中更改基类/特征的方差?

Seb*_*iot 6 scala variance

我想从Scala的不可变映射派生出来.它定义如下:

trait Map[A, +B]
Run Code Online (Sandbox Code Playgroud)

不幸的是,我的实现需要在B中保持不变.我尝试了以下内容,但没有成功:

def +(kv : (A, B)) : MyMap[A, B] = { ... }

override def +[B1 >: B](kv : (A, B1)) : MyMap[A, B1] =
    throw new IllegalArgumentException()
Run Code Online (Sandbox Code Playgroud)

也许有一招@uncheckedVariance

Did*_*ont 1

完全消除协方差当然是不合理的,也是不允许的。\n给定m: Map[A, String]、 和v : Any,你可以这样做val mm : Map[A, Any] = m + v。这就是Map定义所说的,所有实现者都必须遵循。您的类可能是不变的,但它必须实现 Map 的完整协变接口。

\n\n

现在重新定义+抛出错误是一个不同的故事(还不是很健全)。您的新方法的问题+在于,在泛型擦除之后,它与其他+方法具有相同的签名。有一个技巧:添加隐式参数,这样签名中就有两个参数,这使得它与第一个不同。

\n\n
def +(kv : (A,B))(implicit useless: A <:< A) : MyMap[A,B]\n
Run Code Online (Sandbox Code Playgroud)\n\n

(只要找到一个隐式参数,您要查找的隐式参数并不重要。implicit useless: Ordering[String]效果也一样)

\n\n

这样做时,您会遇到常见的超载问题。如果在编译器不知道的情况下添加 B,则会调用失败的方法。最好在那里执行类型检查,以便 B 实例被接受。这需要在您的地图中获取 Manifest[B]\xc2\xa0。

\n