Jul*_*ian 3 java generics scala covariance
当我编写这段代码时,我在Scala中遇到了编译错误
var s: Stack[_ <: Number] = new Stack[Integer];
s.push(new Integer(1)); //compile-error: type mismatch; found :Integer required: _$bqjyh where type _$bqjyh <: Number
s.push(null); //compile-error: type mismatch; found : Null(null) required: _$2 where type _$2 <: Objects.Vehicle
Run Code Online (Sandbox Code Playgroud)
由于通配符,这相当于Java中的协变集合; 它确切的类型在未知,所以我们不能添加东西到堆栈.
但是对于列表,我不会得到同样的错误:
var list: List[_ <: Number] = Nil;
var intList : List[Integer] = new Integer(1) :: Nil;
list = intList ; //no error
list = new Float(2) :: vehicles; //even float allowed
Run Code Online (Sandbox Code Playgroud)
现在,我可以添加甚至float,但事实上我相信list是List的Integers,所以不会Floats允许的.
1)为什么这个列表允许,而不是Stacks?这是由于cons(::)运算符吗?
2)列表的类型是什么?它是动态的吗?
3)为什么在Scala而不是Java中允许这样做?
4)我可以在堆栈中添加一些东西吗?(null在Java中不起作用,因为泛型类型只允许引用类型)
::不是变异操作.这意味着x :: xs将返回一个List类型List[ commonSupertypeOf[ typeOf[x], elementTypeOf[xs] ] ](这不是实际的scala代码,但我希望我的观点能够实现),但它不会改变类型xs.如果xs有类型List[Float]并且x有类型Integer,那么表达式x :: xs将具有类型List[Numeric],但类型xs仍然是List[Float],因此没有任何中断.
add然而,这是一个变异操作.xs.add(x)将添加Integer到Stack其类型是Stack<Float>,这显然是一个错误.
这解释了为什么做事x :: xs并不危险.现在来解释为什么它出现了类型:
的singnature ::上List[A]是: def :: [B >: A] (x: B) : List[B].
这意味着对于任何类型A和B其中B的超类型A,::给定类型的值和类型B列表A将产生类型列表B.因此,当你做一些时someInteger :: someFloats,编译器会推断出现B在Numeric和A现在Float一切正常.
在java术语中,<B supertypeOf A> List<B> prepend(B item)除了supertypeOf不合法的java之外.
| 归档时间: |
|
| 查看次数: |
243 次 |
| 最近记录: |