Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否可以更改Scala中基类/特征的方差?_Scala_Variance - Fatal编程技术网

是否可以更改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?有一个技巧,问

我想从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

有一个技巧,问题是如果从不可变映射派生不变版本,就会破坏类型安全性。例如:

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,并提供对内部不可变映射的完全访问。