classOf[T]、getClass和 class

目录

一、classOf[T]、getClass和 class案例

二、关于协变和逆变

三、总结:



一、classOf[T]、getClass和 class案例

在这里插入图片描述
上面显示了两者的不同之处,getClass 方法得到的是 Class[A]的某个子类,而 classOf[A] 得到是正确的 Class[A],但是去比较的话,这两个类型是equals为true的。

在这里插入图片描述

这里有细微的差别,体现在类型赋值时,因为java里的 Class[T]是不支持协变的,所以无法把一个 Class[_ < : A] 赋值给一个 Class[A]。

在这里插入图片描述

二、关于协变和逆变

1、C[T] A B 其中A <: B

若 C[A]:C[B] C 是 cotravariant
如果 C[A]和C[B]没有父子关系 那么C是nonvariant

2、Scala中是允许你自己定义是否是variant的
class C[+A]{…} C是covariant

[+T], covariant (or “flexible”) in its type parameter T,类似Java中的(? extends T), 即可以用T和T的子类来替换T,里氏替换原则。
 
可以看到List的定义:
 
type List[+A] = scala.collection.immutable.List[A]  
协变的符号是[+A],意味着支持泛型A的子类集合向A进行赋值。 在这个例子里是List的是支持协变的。

class C[-A]{…} C是contrvariant

[-T], contravariant, 类似(? supers T)
 
if T is a subtype of type S, this would imply that Queue[S] is a subtype of Queue[T]
 
只能用T的父类来替换T。是逆里氏替换原则。 在 scala.actors.OutputChannel 这个trait是一个逆变的类型。
 
trait OutputChannel[-Msg] {  
......  
对于OutputChannel[String], 支持的操作就是输出一个string, 同样OutputChannel[AnyRef]也一定可以支持输出一个string, 因为它支持输出任意一个AnyRef(它要求的比OutputChannel[String])

但反过来就不行, OutputChannel[String]只能输出String, 显然不能替换OutputChannel[AnyRef]

class C[A] {…} C是nonvariant(默认)

说明:以上是针对Scala-2.10.x版本的介绍

三、总结:

  1. 协变 [+T], covariant (or “flexible”) in its type parameter T,类似Java中的(? extends T), 即可以用T和T的子类来替换T,里氏替换原则。
  2. 不变 不支持T的子类或者父类,只知支持T本身。
  3. 逆变 [-T], contravariant, 类似(? supers T) 只能用T的父类来替换T。是逆里氏替换原则。
  4. 上界: 只允许T的超类U来替换T。 [U >: T]
  5. 下界: 只允许T的子类U来替代T。 [U <: T]
发布了422 篇原创文章 · 获赞 357 · 访问量 124万+

猜你喜欢

转载自blog.csdn.net/silentwolfyh/article/details/103636877