Scala 性状多类型实例中的类型方差

Scala 性状多类型实例中的类型方差,scala,generics,multiple-inheritance,covariance,traits,Scala,Generics,Multiple Inheritance,Covariance,Traits,考虑 trait Foo[+A, +B] trait Foo1[+A] extends Foo[A, Nothing] trait Foo2[+B] extends Foo[Nothing, B] 新的Foo1[String]和Foo2[Nothing]有效 Foo2[String]的新Foo1[Nothing] 新的Foo1[String]和Foo2[String]不会: error: illegal inheritance; <$anon: Foo1[String] with

考虑

trait Foo[+A, +B]

trait Foo1[+A] extends Foo[A, Nothing]

trait Foo2[+B] extends Foo[Nothing, B]

新的Foo1[String]和Foo2[Nothing]
有效

Foo2[String]的新Foo1[Nothing]

新的Foo1[String]和Foo2[String]
不会:

error: illegal inheritance;
<$anon: Foo1[String] with Foo2[String]> inherits different type instances of trait Foo:
Foo[Nothing,String] and Foo[String,Nothing]
          new Foo1[String] with Foo2[String]
              ^
错误:非法继承;
继承trait Foo的不同类型实例:
Foo[Nothing,String]和Foo[String,Nothing]
使用Foo2[String]新建Foo1[String]
^

在第一种情况下,该实例似乎是
Foo[String,Nothing]
的子类型

同样,在第二种情况下,实例应该是
Foo[String,String]
的子类型


这两者之间的区别是什么,导致只有一个编译?

如果您看到编译器实际上很好地解释了这一点:

: Foo1[String] with Foo2[String]> inherits different type instances of trait Foo:
Foo[Nothing,String] and Foo[String,Nothing]
              new Foo1[String] with Foo2[String]
要解释第一个问题:

new Foo1[String] with Foo2[Nothing]
看看这个例子:

scala> val x = new Foo1[String] with Foo2[Nothing]
x: Foo1[String] with Foo2[Nothing] = $anon$1@58651fd0

scala> val y:Foo[String, Nothing] = x
y: Foo[String,Nothing] = $anon$1@58651fd0
根据规范,具有特征的多个的实例化从左到右进行。因此,首先实例化
Foo1
。执行
newfoo1[String]
将为您提供
Foo[String,Nothing]
<代码>使用Foo2[Nothing]将为您提供
Foo[Nothing,Nothing]
。现在,
Foo
是其第一个类型参数的共同变体。简言之,这是有效的:

scala> val a = new Foo[Nothing, Nothing]{}
a: Foo[Nothing,Nothing] = $anon$1@134593bf

scala> val b:Foo[String, Nothing] = a
b: Foo[String,Nothing] = $anon$1@134593bf
因此,可以使用Foo[String,Nothing]代替Foo[Nothing,Nothing]。这使您能够实例化
y

在下列情况下:

new Foo1[String] with Foo2[String]
newfoo1[String]
给出
Foo[String,Nothing]
<代码>与Foo2[String]一起给出
Foo[Nothing,String]
。两者都是矛盾的(由于其第二个参数:

与Foo2[String]
(Foo[Nothing,String])一起变成Foo[String,String]

scala> val p :Foo[String, String] = new Foo[Nothing, String]{}
p: Foo[String,String] = $anon$1@39529185
但是Foo[String,String]不能成为Foo[String,Nothing]。(
val p:Foo[String,Nothing]=new Foo[Nothing,String]{}
失败)

因此是错误的


在变体中 如果Foo的第一个参数不是variant,则它不起作用:

scala> trait Foo[A, +B]
defined trait Foo

scala> trait Foo1[A] extends Foo[A, Nothing]
defined trait Foo1

scala> trait Foo2[+B] extends Foo[Nothing, B]
defined trait Foo2

scala> new Foo1[String] with Foo2[Nothing]
<console>:11: error: illegal inheritance;
 <$anon: Foo1[String] with Foo2[Nothing]> inherits different type instances of trait Foo:
Foo[Nothing,Nothing] and Foo[String,Nothing]
              new Foo1[String] with Foo2[Nothing]

它之所以有效,是因为现在:Foo[String,String]可以变成Foo[String,Nothing]

“Foo[String,Nothing]没有@PaulDraper,你正在做相反的事情:)。它是
val v:Foo[String,Nothing]=new Foo[String,String]{
但它失败了。@Paul Draper同意。我想展示的是协方差关系,而不是

scala> trait Foo[+A, -B]
defined trait Foo

scala> trait Foo1[+A] extends Foo[A, Nothing]
defined trait Foo1

scala> trait Foo2[-B] extends Foo[Nothing, B]
defined trait Foo2

scala> new Foo1[String] with Foo2[String]
res0: Foo1[String] with Foo2[String] = $anon$1@77468bd9

scala> new Foo1[String] with Foo2[Nothing]
res1: Foo1[String] with Foo2[Nothing] = $anon$1@51016012