是否可以更改Scala中基类/特征的方差?
我想从Scala的不可变映射中派生。其定义如下:是否可以更改Scala中基类/特征的方差?,scala,variance,Scala,Variance,我想从Scala的不可变映射中派生。其定义如下: trait Map[A, +B] 不幸的是,我的实现需要在B中保持不变。我尝试了以下方法,但没有成功: def +(kv : (A, B)) : MyMap[A, B] = { ... } override def +[B1 >: B](kv : (A, B1)) : MyMap[A, B1] = throw new IllegalArgumentException() 也许@uncheckedVariance?有一个技巧,问
trait Map[A, +B]
不幸的是,我的实现需要在B中保持不变。我尝试了以下方法,但没有成功:
def +(kv : (A, B)) : MyMap[A, B] = { ... }
override def +[B1 >: B](kv : (A, B1)) : MyMap[A, B1] =
throw new IllegalArgumentException()
也许
@uncheckedVariance
?有一个技巧,问题是如果从不可变映射派生不变版本,就会破坏类型安全性。例如:
val dm = DiotMap(1 -> "abc")
val m: Map[Int, Any] = dm
此声明有效,因为
Map
是协变的。如果您的集合无法处理协方差,那么当我使用m
时会发生什么?完全消除协方差当然是不合理的,也是不允许的。
给定m:Map[A,String]
和v:Any
,您可以执行val mm:Map[A,Any]=m+v
。这就是Map
definition所说的,所有实现者都必须遵循。您的类可能是不变的,但它必须实现Map的完全协变接口
现在重新定义+
抛出错误是另一回事(还不太合理)。新的+
方法的问题是,在泛型擦除之后,它与另一个+
方法具有相同的签名。这里有一个技巧:添加隐式参数,这样签名中就有两个参数,这使它不同于第一个参数
def +(kv : (A,B))(implicit useless: A <:< A) : MyMap[A,B]
def+(kv:(A,B))(隐式无用:A也许你可以使用成员映射而不是派生?还有,为什么它需要是不变的?我想(虽然我不知道多少Scala)唯一需要不变性的时候是如果它既可以是源也可以是汇,但是映射是不可变的,所以它不能是汇。我想实现一个双向映射。如果我实现了映射,这没什么大不了的,只需要委托给定义前向映射和后向映射的两个内部映射,但在这种情况下我需要不变性。也许你可以有一个轻接口BiMap的rface(主要是返回新BiMap的“修改”方法),不扩展Map,并提供对内部不可变映射的完全访问。