泛型的基本介绍
- 如果我们要求函数的参数可以接受任意类型。可以使用泛型,这个类型可以代表任意的数据类 型。
- 例如 List,在创建 List 时,可以传入整型、字符串、浮点数等等任意类型。那是因为 List 在 类定义时引用了泛型。比如在 Java 中:
public interface List<E> extends Collection<E>
上界(Upper Bounds)/下界(lower bounds)
java上界
在 Java 泛型里表示某个类型是 A 类型的子类型,使用 extends 关键字,这种形式叫 upper
bounds(上限或上界),语法如下:
<T extends A>
或用通配符的形式:
<? extends A>
scala上界
在 scala 里表示某个类型是 A 类型的子类型,也称上界或上限,使用 <: 关键字,语法如下: [T <: A]
//或用通配符:
[_ <: A]
object UpperBoundsDemo01 {
def main(args: Array[String]): Unit = {
val compareInt = new CompareInt(10, 40)
println(compareInt.greater) // 40
//第一个用法
val commonCompare1 = new CommonCompare(Integer.valueOf(10), Integer.valueOf(40)) //Int
println(commonCompare1.greater)
//第二个用法
val commonCompare2 = new CommonCompare(java.lang.Float.valueOf(1.1f), java.lang.Float.valueOf(2.1f)) //Fl
println(commonCompare2.greater)
//第3种写法使用了隐式转换
//implicit def float2Float(x: Float): java.lang.Float = x.asInstanceOf[java.lang.Float]
val commonCompare3 = new CommonCompare[java.lang.Float](10.1f, 21.1f) //
println(commonCompare3.greater)
}
}
/*
编写一个通用的类,可以进行Int之间、Float之间、等实现了Comparable接口的值直接的比较.//java.lang.Integer
分别使用传统方法和上界的方式来完成,体会上界使用的好处.
*/
//传统方法
class CompareInt(n1: Int, n2: Int) {
//返回较大的值
def greater = if (n1 > n2) n1 else n2
}
//使用上界(上限)来完成
//说明
//1. [T <: Comparable[T]] 表示T类型是Comparable 子类型
//2. 即你传入的T类要继承Comparable接口
//3. 这样就可以使用compareTo方法
//4. 这样的写法(使用上界的写法)通用性比传统的好
class CommonCompare[T <: Comparable[T]](obj1: T, obj2: T) {
def greater = if (obj1.compareTo(obj2) > 0) obj1 else obj2
}
Java下界
在 Java 泛型里表示某个类型是 A 类型的父类型,使用 super 关键字
<T super A>
scala下界
在 scala 的下界或下限,使用 >: 关键字,语法如下:
[T >: A]
//或用通配符:
[_ >: A]
scala下界的使用小结
def biophony[T >: Animal](things: Seq[T]) = things
- 对于下界,可以传入任意类型
- 传入和 Animal 直系的,是 Animal 父类的还是父类处理,是 Animal 子类的按照 Animal 处理
- 和 Animal 无关的,一律按照 Object 处理
- 也就是下界,可以随便传,只是处理是方式不一样
- 不能使用上界的思路来类推下界的含义
视图界定
- T <% Comparable[T] 说明 T是 Comparable子类型
- T
<%
Comparable[T] 和 T<:
Comparable[T] 区别就是视图界定支持隐式转换
- 视图界定不但支持以前上界的写法,同时支持简洁的写法val compareComm01 = new CompareComm(1, 20)
- 推荐大家使用视图界定而不是上下界, 功能更强大
object ViewBoundsDemo01 {
def main(args: Array[String]): Unit = {
//使用了隐式转换
val compareComm01 = new CompareComm(1, 20)
println(compareComm01.greater)
val compareComm2 = new CompareComm(Integer.valueOf(20), Integer.valueOf(30))
println(compareComm2.greater)
//以前 <: 上界
val compareComm4 = new CompareComm[java.lang.Float](201.9f, 30.1f)
println(compareComm4.greater)
//上面的小数比较,在视图界定的情况下,就可以这样写了
//这里会进行隐式转换
val compareComm5 =
new CompareComm(201.9f, 310.1f)
println(compareComm5.greater)
}
}
class CompareComm[T <% Comparable[T]](obj1: T, obj2: T) {
def greater = if (obj1.compareTo(obj2) > 0) obj1 else obj2
}
上下文界定(Context bounds):
与 view bounds 一样 context bounds(上下文界定)也是隐式参数的语法糖。为语法上的方便, 引入 了”上下文界定”这个概念, 至于上下文界定的具体的应用,
详情请参考我的博客Scala之 隐式值 隐式函数 隐式参数 隐式类