概述:类型参数,说白了就是泛型,什么是泛型?广泛的类型,啥类型都有可能,是一种更加通用的表示,或者定义。
Scala中定义泛型的方式和java中稍微有点不同,java中<>,scala中[],其他都一样。
?:
/**
* 泛型
*/
object GenericOps {
def main(args: Array[String]) {
val tool = new Tool[Int]()
println(tool.add(1,2))
println(tool.add(32,54,4,5))
val tool1 = new Tool[String]()
println(tool1.add("first","last"))
}
}
class Tool[T] {
def add(a:T,b:T) : T = {
a
}
def add(arr:T*):T={
arr(0)
}
}
虽然上面定义了泛型类,但是不是很灵活,因为一旦在成员上面使用了这个类的泛型,那么便无法再使用其它类型。
?:
object _03GenericOps {
def main(args: Array[String]) {
val tool = new Tool[Int]()
tool.show[String]("show","your","name")
}
}
class Tool[T] {
def show[Q](arr:Q*): Unit ={
println(arr.mkString(","))
}
}
说明在方法上面使用的泛型,会覆盖掉类上定义的泛型
Scala中的泛型界/限定的概念和java中的泛型的限定是一样的。
先用例子给大家看看,然后咱们总结一下:
?:
def main(args: Array[String]): Unit = {
val array = Array[Int](1, 5, 3, 5, 6, 7, 2, 9)
val strArr = Array[String]("abc", "def", "rst", "lmn")
println("排序前的数组:" + array.mkString("[", ", ", "]"))
selectSort(array)
println("排序后的数组:" + array.mkString("[", ", ", "]"))
/*
val aa:Int = 3
val bb = 4
aa.compareTo(bb)
*/
def selectSort[T <% Comparable[T]](arr:Array[T]): Unit ={
for (i <- 0 until arr.length ){
for (j <- i until arr.length){
if(arr(i).compareTo(arr(j))>0){
swap(arr,i,j)
}
}
}
}
def swap[T](arr:Array[T],i:Int,j:Int): Unit ={
var temp = arr(i)
arr(i) = arr(j)
arr(j) = temp
}
}
总结:
上限限定(掌握)
在java中的语法结构
在scala中语法结构[T <: Xxx]
如果使用通配符的话,用?
下限限定(了解)
在java中的语法结构
在scala中语法结构[T >: Xxx]
通配符用_
在scala中让一个类型具备比较性,一般都是用Ordered[T] --对应–> java中的Comparable[T]
在scala中让一个集合提供比较器,一般都用Ordering[T] --定义–>java中的 Comparator[T]
这里看到,Int类型没有直接扩展Comparable接口,所以我们不能直接对齐进行使用xx.compareTo的操作,也就是说如果类型[T <: Comparable[T]]的,此时T是Int,编译无法通过,但是只要做一下稍微的搞定即可[T <% Comparable[T]],编译就可以通过,当然如果想让之前的代码通过,只需要将Int该成Integer即可。
val aaa:Int = 3
val bb = 4
aaa.compareTo(bb),这个是直接可以进行操作,这和上面Int没有扩展Comparable矛盾,所以肯定在背后有人来帮助
Int做了实现,达到的效果就是对Int做了包装,RichInt extends Comparable[RichInt]
以后但凡出现Int,会自动的转化为RichInt,这个操作就是隐式转化
在定义的使用手动进行类型转化,就用到了scala中视图界定 <%
在Java中泛型的一个特点,在java中规定,=左右两侧的泛型都必须是一致,
其实这就是多态,父类引用指向子类对象
List<Object> list = new ArrayList<Person>();
list.add(new Person());
list.add(new Student());
List<Person> list2 = new ArrayList<Object>();
list2.add(new Person());
list2.add(new Student());
以上两种操作方式都是错误的,不被允许的。把这种操作称之为泛型的继承。
那么在scal中是如何规定的呢?
在默认情况下,scala也不允许出现上述泛型继承的现象。
但是非常灵活的scala,在特殊情况下是允许这些情况的方式,也就是对应的协变和逆变。在定义泛型的时候,添加一个符号即可[+T]协变,[-T]逆变。
协变指的是等号左侧的泛型是右侧的超类,逆变指的是等号左侧的泛型是右侧的子类。
多用于集合的操作。
object _04T {
def main(args: Array[String]) {
val list1:MyList1[Object] = new MyList1[Person]()
val list2:MyList2[Person] = new MyList2[Object]()
val list3:List[Object] = List[Person]()
}
class MyList1[+T] { //把这种泛型的继承称之为协变
}
class MyList2[-T] {//把这种泛型的继承称之为逆变
}
}
class Person{
}