1、类型变量界定(Type Variable Bound):
// 编译错误
def typeVariable[T](a: T, b: T) = {
if (a.compareTo(b) > 0) 1
else -1
}
// 通过编译
def typeVariable[T <: Comparable[T]](a: T, b: T) = {
if (a.compareTo(b) > 0) 1
else -1
}
对泛型做了约束,有点类似java中的继承
2、视图界定(View Bound):
def typeVariable[T <: Comparable[T]](a: T, b: T) = {
if (a.compareTo(b) > 0) 1
else -1
}
val v1 = typeVariable("scala", "java")
println(v1) // scala
运行结果为:scala,但是,如果我们输入数字的话,便会报错:
val v2 = typeVariable(100, 200)
println(v2)
Error:(15, 12) inferred type arguments [Int] do not conform to method typeVariable's type parameter bounds [T <: Comparable[T]]
val v2 = typeVariable(100, 200)
^
因为我们的Int类型并没有遵循我们的范型约束。如果我们此时想成功运行的话,就需要进行一次隐式转换,将Int类型转换成支持Comparable[T]的类型,那么,我们的视图界定便能出场了:
def typeVariable[T <% Comparable[T]](a: T, b: T) = {
if (a.compareTo(b) > 0) a
else b
}
val v2 = typeVariable(100, 200)
println(v2) // 200
从代码中发现,范型限定时,我们将"<:"改为了"<%",这样,原本的类型变量界定就转换成了视图界定,而视图界定帮我们进行了隐式转换,将Int转换成了支持Comparable[T]的RichInt类型。
编写代码时,"<%"的限定较为宽松,不仅继承了Comparable[T]的类能够顺利运行,而且通过隐式转换而来的继承Comparable[T]的类也能够顺利运行。
3、上界(Upper Bound)、下界(Lower Bound):
有上界,那么也有下界,上界我们用"<:"来表示,例如:A <: B,表示B为A的上界,在java中即A继承B。
下界用">:"来表示,例如A >: B,表示B为A的下界,此时B继承A。
4、上下文界定(Context Bound):
上下文界定的类型参数形式为T:M的形式,其中M是一个泛型类,这种形式要求存在一个M[T]类型的隐式值:
class Person(val age: Int) {
println("person==> " + age)
}
// PersonOrdering继承了Ordering[T],而Ordering[T]又继承了Comporator[T],所以下面方法中有compare(x: T, y: T)方法
class PersonOrdering extends Ordering[Person] {
override def compare(x: Person, y: Person): Int = {
if (x.age > y.age) 1 else -1
}
}
// 该类定义了一个上下文界定,意思是
// 在其作用域内,必须有一个Ordering[T]的隐式值,而这个隐式值可以作用于内部的方法
class Pair[T: Ordering](val first: T, val second: T) {
// 该方法需要一个类型为Ordering[T]的隐式参数
def old(implicit ord: Ordering[T]) = {
if (ord.compare(first, second) > 0) first else second
}
}
// 定义一个隐式值,类型为Ordering[T]
implicit val po = new PersonOrdering
val p = new Pair(new Person(18), new Person(19))
// 调用old方法时,不需要传入参数,根据我们的上下文界定要求,po满足要求,因此作为参数传入old
println(p.old.age) // 19
完整代码:
package scala.context
object Test {
//类型变量界定(Type Variable Bound)
//编译错误
/*def typeVariable[T](a: T, b: T) = {
if (a.compareTo(b) > 0) 1
else -1
}*/
// 通过编译
def typeVariable[T <: Comparable[T]](a: T, b: T) = {
if (a.compareTo(b) > 0) 1
else -1
}
val v1 = typeVariable("scala", "java")
println(v1) // scala
//输入数字的话,便会报错:
//val v2 = typeVariable(100, 200)
//println(v2)
//Error:(15, 12) inferred type arguments [Int] do not conform to method typeVariable's type parameter bounds [T <: Comparable[T]]
//val v2 = typeVariable(100, 200)
//进行一次隐式转换,将Int类型转换成支持Comparable[T]的类型
//类型变量界定就转换成了视图界定
def typeVariable1[T <% Comparable[T]](a: T, b: T) = {
if (a.compareTo(b) > 0) a
else b
}
val v2 = typeVariable(100, 200)
println(v2) // 200
}
package scala.context
class Person(val age: Int) {
println("person==> " + age)
}
// PersonOrdering继承了Ordering[T],而Ordering[T]又继承了Comporator[T],所以下面方法中有compare(x: T, y: T)方法
class PersonOrdering extends Ordering[Person] {
override def compare(x: Person, y: Person): Int = {
if (x.age > y.age) 1 else -1
}
}
// 该类定义了一个上下文界定,意思是
// 在其作用域内,必须有一个Ordering[T]的隐式值,而这个隐式值可以作用于内部的方法
class Pair[T: Ordering](val first: T, val second: T) {
// 该方法需要一个类型为Ordering[T]的隐式参数
def old(implicit ord: Ordering[T]) = {
if (ord.compare(first, second) > 0) first else second
}
}
object ContextBoundTest {
def main(args: Array[String]): Unit = {
// 定义一个隐式值,类型为Ordering[T]
implicit val po = new PersonOrdering
val p = new Pair(new Person(18), new Person(19))
// 调用old方法时,不需要传入参数,根据我们的上下文界定要求,po满足要求,因此作为参数传入old
println(p.old.age) // 19
}
}
网友评论