Pau*_*per 2 generics scala multiple-inheritance covariance traits
考虑
trait Foo[+A, +B]
trait Foo1[+A] extends Foo[A, Nothing]
trait Foo2[+B] extends Foo[Nothing, B]
Run Code Online (Sandbox Code Playgroud)
new Foo1[String] with Foo2[Nothing]
作品.
new Foo1[Nothing] with Foo2[String]
作品.
new Foo1[String] with 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]
^
Run Code Online (Sandbox Code Playgroud)
似乎在第一种情况下,实例是一个子类型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]
Run Code Online (Sandbox Code Playgroud)
解释第一个:
new Foo1[String] with Foo2[Nothing]
Run Code Online (Sandbox Code Playgroud)
看看这个例子:
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
Run Code Online (Sandbox Code Playgroud)
根据规范,多个with
特征的实例化从左到右发生.所以首先Foo1
实例化.做new Foo1[String]
给你Foo[String, Nothing]
.with 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
Run Code Online (Sandbox Code Playgroud)
因此,您可以使用Foo [String,Nothing]而不是Foo [Nothing,Nothing].这使您能够实例化y
.
的情况下:
new Foo1[String] with Foo2[String]
Run Code Online (Sandbox Code Playgroud)
new Foo1[String]
给Foo[String, Nothing]
.with Foo2[String]
给Foo[Nothing, String]
.而且它们都是矛盾的(由于它的第二个参数:
with 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
Run Code Online (Sandbox Code Playgroud)
但是Foo [String,String] 不能成为Foo [String,Nothing].(val p :Foo[String, Nothing] = new Foo[Nothing, String]{}
失败)
因此错误.
In-Variant 如果Foo的第一个参数不是in-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]
Run Code Online (Sandbox Code Playgroud)
Contra-Variance 如果Foo在第二种类型上具有反变量,则两种语句都有效
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
Run Code Online (Sandbox Code Playgroud)
它只是起作用,因为现在:Foo [String,String] 可以成为Foo [String,Nothing]
归档时间: |
|
查看次数: |
179 次 |
最近记录: |