Scala学习(五)——泛型

Scala学习(五)——泛型

本站内容版权属于本人。转载须告知本人,写明出处,并在文首提供指向本站对应文章的链接。
本文链接:Scala学习(五)——泛型
简介

在Java或者C++里面,像列表(List)这些数据结构,在编写的时候,都不需要指定其中元素的类型,而是构造的时候指定,这一特性就称为泛型。同样,Scala中也提供了泛型,而且功能比Java的泛型更加强大。

类的泛型

可以给一个类添加泛型,这样,在编写的时候就不需要考虑这一类型的具体情况,而是使用一个标记来注明。泛型的定义列表用[]包含,用,分隔,卸载类名之后,构造函数参数列表之前,泛型的具体名称可以任意定义(比如如下代码中的KV):

类似构造函数,如果要继承的类包括泛型,那么继承时也需要写泛型的类型:

不过这里Pair的泛型其实是可以通过构造函数传值的类型猜测出来的,所以可以省略:

这样,类名在声明或者新建实例的时候也需要写明泛型的类型:

当然,上面这句话的最简写法是这样的,可以猜到的类型和泛型设定都被省略掉了:

方法的泛型

除了类可以设置泛型,方法也可以设置泛型。写法是在方法名后面加上泛型列表。下面这个方法完成了任意类型T数组的赋值操作(没有实际意义):

调用时同样可以显式写明泛型类型或者省略:

泛型的上下界

在定义泛型列表的时候可以使用<:>:规定泛型元素的上下界:

可以使用with关键字对多个特征进行限定:

协变和逆变

简而言之,协变和逆变是指类型AClass[T]会随着泛型参数T的继承关系而产生继承关系。声明时只需要在泛型参数前加+或者-就可以获得协变或者逆变特性:

以下的实例说明了协变和逆变的继承关系:

如果不加协变或者逆变的符号,那么:

在使用中,协变用于写,比如作为参数,可以输入其子类,逆变用于读,比如作为函数返回值,可以接受其父类。协变和逆变这一设定,是Java所不具有的,体现了Scala的实用性。

可实例化的泛型

大家都知道Java的泛型并不能实例化,尤其是像List.toArray这种方法,还需要自己实例化一个相应数组传参进去,不然就只能返回Object数组。Scala运行在JVM上,也存在这样的问题,不过Scala提供了一种较简便的方法来解决这个问题。下面用一个方法来说明:

这个方法输入一个任意类型的值,输出一个相应的只有一个元素数组。值得注意的是,在泛型参数T之后增加了:ClassTag。这一操作使调用函数时,会将泛型的类型信息记录在一个ClassTag类型的对象里,之后可以通过这个对象调用Java反射构造数组。有关这种写法的意义将在以后说明。

总结

Scala的泛型系统相比Java完善了许多,相比鸡肋一般的Java泛型,Scala泛型的完成度几乎可以媲美C++模板。用好泛型可以使程序可扩展性更强,结构更加严密。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据