【大纲】
【正文】
1.【结论】概念
泛型,即泛指某些种具体的数据类型,用[数据类型]表示
之前在数组和集合中使用过 如 Array[Int]
2.【结论】泛型方法
0.作用
将泛型[T]定义在方法的声明上,让方法的参数使用此泛型[T]来作为参数的类型,则调用方法时,实际给的参数的数据类型是什么,方法中的[T]就是什么
# 注意:
T可以是任意大写字母
示例
# 不使用泛型时:只能获取Int类型数组的中间元素
object T1 {
def getMid(a:Array[Int]) = a(a.length / 2)
def main(args: Array[String]): Unit = {
val b = getMid(Array(1,2,3,4,5))
println(b) // 效果:3
}
}
# 使用泛型:可以获取任何类型数组的中间元素
object T1 {
def getMid[T](a:Array[T]) = a(a.length / 2)
def main(args: Array[String]): Unit = {
val b = getMid(Array(1,2,3,4,5)) // val b = getMid[Int](Array(1,2,3,4,5)) [Int]可省略
println(b) // 效果:3
val c = getMid(Array('a','b','c')) // val c = getMid[Char](Array('a','b','c')) [Char]可省略
println(c) // 效果:b
}
}
3.【结论】泛型类
0.作用
将泛型[T]定义在类的声明上,让类的成员参数使用此泛型[T]来作为数据类型,则创建对象时,实际给的成员的数据类型是什么,类中的[T]就是什么
示例
# 需求:
0.定义一个Pair类,该类包含两个成员字段,且两个字段的类型不固定
1.创建不同类型的Pair类对象,并打印
# 实现:
object TClass {
class Pair[T](var a:T, var b:T)
def main(args: Array[String]): Unit = {
val p1 = new Pair(10, 20) // val p1 = new Pair[Int](10, 20) [Int]可省略
println(p1.a, p1.b) // 效果:(10,20)
val p2 = new Pair("a", "b") // val p2 = new Pair[String]("a", "b") [String]可省略
println(p2.a, p2.b) // 效果:(a,b)
}
}
4.【结论】泛型特质
0.作用
将泛型定义在特质的声明上,让特质的成员使用此泛型作为数据类型,则在子类继承特质时,指定特质的数据类型,即可传递给特质的泛型
示例
object TTrait {
trait Person[T]{
val name:T
def run(sex:T) = println(sex)
}
object Children extends Person[String]{ // 声明了特质的实际泛型是[String]
override val name: String = "小学生"
}
def main(args: Array[String]): Unit = {
val name = Children.name
println(name) // 效果:小学生
Children.run("跑不掉") // 效果:跑不掉
}
}
5.【结论】泛型的上界
[T <: 泛型的上界数据类型],代表泛型T的数据类型,必须是上界数据类型或其子
示例
object TUp {
class Person
class Student extends Person
// 定义泛型方法 指定泛型的上届
def demo[T <: Person](arr:Array[T]) = println(arr)
def main(args: Array[String]): Unit = {
val a = demo(Array(new Person))
val b = demo(Array(1,2)) // 编译会报错 因为只能传入Person或者它的子类型
}
}
6.【结论】泛型的下界
0.下界:
[T >: 泛型的下界数据类型],代表泛型T的数据类型,必须是下界数据类型或其父
1.上下界:
[T >: 泛型的下界数据类型 <: 泛型的上界数据类型]
示例
# 泛型的下界
object TDown {
class Person
class Policeman extends Person
class Superman extends Policeman
def demo[T >:Policeman](arr:Array[T]) = println(arr)
def main(args: Array[String]): Unit = {
demo(Array(new Policeman)) // 效果:[Lcom.wsy.TDown$Policeman;@23223dd8
demo(Array(new Person)) // 效果:[Lcom.wsy.TDown$Person;@4ec6a292
demo(Array(new Superman)) // 会报错 泛型规定了只能是Policeman及其父
}
}
# 泛型的上下界
object TDown {
class Person
class Policeman extends Person
class Superman extends Policeman
def demo[T >:Policeman <:Policeman](arr:Array[T]) = println(arr)
def main(args: Array[String]): Unit = {
demo(Array(new Policeman)) // 效果:[Lcom.wsy.TDown$Policeman;@23223dd8
// demo(Array(new Person)) // 会报错 泛型规定了只能是Policeman
demo(Array(new Superman)) // 会报错 泛型规定了只能是Policeman
}
}
7.【结论】泛型类的非变
0.作用
类A是类B的父,但Pair[A]和Pair[B]之间没有任何关系
1.语法
class Pair[T]{}
# 注意:泛型类默认就是非变
示例
object Tf {
class Super
class Sub extends Super
class Temp1[T]
def main(args: Array[String]): Unit = {
val t1:Temp1[Sub] = new Temp1[Sub]()
// val t2:Temp1[Super] = new Temp1[Sub] // 效果:会报错 Temp1[Super]和Temp1[Sub]没有任何子父关系
// val t3:Temp1[Sub] = new Temp1[Super] // 效果:会报错 Temp1[Sub]和Temp1[Super]没有任何子父关系
}
}
8.【结论】泛型类的协变
0.作用
类A是类B的父,Pair[A]也是Pair[B]的父
1.语法
class Pair[+T]{}
示例
object Tx {
class Super
class Sub extends Super
class Temp1[+T]
def main(args: Array[String]): Unit = {
val t1:Temp1[Sub] = new Temp1[Sub]()
val t2:Temp1[Super] = new Temp1[Sub]
// val t3:Temp1[Sub] = new Temp1[Super] // 效果:会报错 因为Temp1[Sub]是Temp1[Super]的子
}
}
9.【结论】泛型类的逆变
0.作用:
类A是类B的父,Pair[A]是Pair[B]的子
1.语法:
1.语法
class Pair[-T]{}
示例
object Tn {
class Super
class Sub extends Super
class Temp1[-T]
def main(args: Array[String]): Unit = {
val t1:Temp1[Sub] = new Temp1[Sub]()
// val t2:Temp1[Super] = new Temp1[Sub] // 效果:会报错 因为Temp1[Super]是Temp1[Sub]的子
val t3:Temp1[Sub] = new Temp1[Super]
}
}