一.初解
当构建一个类或者函数时,如果我们不知道(或者说不确定)传入的参数的具体数据类型,这时候可以泛型,例子如下:
- 1-1例子:
object test0 extends App{
val str = "123"
val intv =123
val strTest = new Test[String](str)
val intTest = new Test[Int](intv)
strTest.check;
intTest.check;
}
class Test[T](val v:T){
def check = {
if(v.isInstanceOf[String]){
println("the param is String");
}
if(v.isInstanceOf[Int]){
println("the param is Int");
}
}
}
-
結果
the param is String
the param is Int -
結論
很多时候我们都需要用到泛型,在web中最常见的就是在用java构建DAO层时,我们往往不知道传入的类型是什么,但是很多时候的操作都是一样的,如增删改查。用泛型+反射的模式可以写一个基于上述操作的通用的模板让所有的需要访问数据库的service层类去调用
二.界定(Bonds)
- 2-1 例子
class Pair[T](val first:T,val second:T){
def smaller = if(first.compareTo(second) < 0) first else second //编译器报错,因为编译器不能确定T具有compareTo的方法
}
object test1 extends App{
val a="3"
val b = "2"
val pair = new Pair(a,b);
print(pair.smaller);
}
所以改進如下
class Pair[T<:Compareable[T]](val first:T,val second:T){
def smaller = if(first.compareTo(second) < 0) first else second
}
修改后就可以运行了。原因是参数的界定是用来限制传入的参数的类型,代表该类型具有这样的一个特性。
- 2-2 例子
object test1 extends App{
val a=3 // 改成整型
val b =2 // 改成整型
val pair = new Pair(a,b); // 这里将会报错,因为整型不是Compareable的子类,不具有compareto方法
print(pair.smaller);
}
这时候把Pair的界定改成浏览界定<%,这个界定符可以隐式地转换类型
class Pair[T<%Comparable[T]](val first:T,val second:T){
def smaller = if(first.compareTo(second) < 0) first else second
}
- 2-3例子
class Pair[T : Ordering](val first: T, val second: T) {
def smaller(implicit ord: Ordering[T]) =
if (ord.compare(first, second) < 0) first else second
}
上下文界定符 “:”意味着可以隐式地转换成Ordering[T]
三.類型約束
类型约束也可以给你用来限制类型,方式有三:
T =:= U
T <:< U
T <%< U
These constraints test whether T equals U, is a subtype of U, or is view-convertible to U.
- 3-1例子:
object test3 extends App{
val first = 123
val second =346
val p = new Pair1[Int](first,second) //这里未调用smaller,不报错
p.smaller;// 这里会报错,因为first,second被检测到不符合
}
class Pair1[T](val first: T, val second: T){
// 下面的方法调用了类型约束,当被调用时才会检测约束
def smaller(implicit ev: T <:< Comparable[T]) =
if (first.compareTo( second) < 0) first else second
}
四.視圖界定
泛型视图限定:表示把传入不是Comparable[T]类型的隐式传换为Comparable[T]类型,Comparable[T]:为T下界,T:为Comparable[T]上界
/*
* <%泛型视图限定符,表示把传入不是Comparable[T]类型的 隐式传换 为Comparable[T]类型
* Comparable[T]:为T下界,T:为Comparable[T]上界
*/
class PairNotPerfect[T <% Comparable[T]](val first: T, val second: T) {
// compareTo方法进行比较,如果大于0返回first
def bigger = if (first.compareTo(second) > 0) first else second
}
/*
* <%泛型视图限定符,表示把传入不是Ordered[T]类型的 隐式传换 为Ordered[T]类型
* Ordered[T]:为T下界,T:为Ordered[T]上界
* Ordered继承: extends Any with java.lang.Comparable[A]
*/
class PairBetter[T <% Ordered[T]](val first: T, val second: T) {
def bigger = if (first.compareTo(second) > 0) first else second
}
object ViewVariablesBounds {
def main(args: Array[String]): Unit = {
// 函数调用
var pair = new PairNotPerfect("Spark", "Hadoop");
// 执行结果:Spark
println(pair.bigger)
// 函数调用,Int类型进行隐式转换,将Int -> RichInt,RichInt实现了Comparable接口
var pairInt = new PairNotPerfect(3,5)
// 执行结果:5
println(pairInt.bigger);
// 函数调用,Int类型进行隐式转换,将String -> RichString,RichString实现了Comparable接口
var pairBetterStr = new PairBetter("Java","Scala");
println(pairBetterStr.bigger);
// 函数调用
var pairBetterInt = new PairBetter(20, 12);
// 执行结果:Spark
println(pairBetterInt.bigger)
}
}
五.上下文界定
上下文界定:上下文界定是隐式参数的语法糖。如:Ordering:可以进行隐式转化的T类型。
class PairOrdering[T: Ordering](val first: T, val second: T) {
// compareTo方法进行比较,如果大于0返回first
def bigger(implicit ordered: Ordering[T]) = if (ordered.compare(first, second) > 0) first else second
}
object ContextBounds {
def main(args: Array[String]): Unit = {
// 函数调用
var pair = new PairOrdering("Spark", "Hadoop")
// 执行结果:Spark
println(pair.bigger)
}
}
网友评论