泛型
[T <: UpperBound] 上界,定义个上限,不能超过[T >: LowerBound] 下界,定义下限,不能低于[T <% ViewBound] 视图界定,如果你想标记某一个泛型可以隐式的转换为另一个泛型,可以使用[T <% Comparable[T]],由于scala的Int类型没有实现Comparable接口,所以我们需要将Int类型隐式的转换为RichInt类型[T : ContextBound] 上下文界定[+T] 斜变,方法返回[-T] 逆变,方法参数
在java中,T同时是A和B的子类型,称为多界,形式如: <T extends A & B>
在scala中,对上界和下界不能有多个,但是可以使用混合类型,如: [T <: A with B]
在java中,不支持下界的多界形式.如: <T super A & B>这是不支持的
在scala中,对复合类型依然可以使用下界,如: [T >: A with B]
例子
[T <: UpperBound]
package genclass Boy(val name: String, var faceValue: Int) extends Comparable[Boy]{override def compareTo(o: Boy): Int = {this.faceValue - o.faceValue}}
package genclass MrRight[T <: Comparable[T]] {// 方法也可以加泛型//def choose[T <: Comparable[T]] (first: T, second: T): T = {def choose(first: T, second: T): T = {if (first.compareTo(second) > 0) first else second}}object MrRight {def main(args: Array[String]): Unit = {val mr = new MrRight[Boy]val b1 = new Boy("xiaowang", 99)val b2 = new Boy("xiaoxia", 77)mr.choose(b1, b2)}}
[T <% ViewBound]
package genclass Girl(val name: String, var faceValue: Int) {}
package genobject MyPreDef {//隐式转换implicit def girl2Ordered(g : Girl) = new Ordered[Girl] {//比较规则放这里override def compare(that: Girl): Int = {g.faceValue - that.faceValue}}}
package gen//viewbound,必须有个隐式转换的方法class MissRight[T <% Ordered[T]] {def choose(first: T, second: T): T = {if (first > second) first else second}}object MissRight {def main(args: Array[String]): Unit = {//要在new之前导入,隐式转换,隐式转换里面写比较规则import MyPreDef.girl2Orderedval mr = new MissRight[Girl]val g1 = new Girl("ab", 90)val g2 = new Girl("mr", -1)val result = mr.choose(g1, g2)println(result.name)}}
[T : ContextBound]
Manifest上下文界定
Manifest是scala2.8引入的一个特质,用于编辑器在运行时也能获取泛型类型的信息.在jvm上,泛型参数类型T在运行时是被擦拭掉的,编译器把T当作Object来对待,所以T的具体信息是无法得到的.
为了使在运行时得到T的信息,scala需要额外通过Manifest来存储T的信息,并作为参数用在方法的运行时上下文
def test[T](_x:T_ m:Manifest[T]) {...}
有了Manifest[T]这个记录T类型信息的参数m,在运行时就可以根据m来更准确的判断T了,但如果每个方法都这么写,让方法的调用者要额外传入m参数,非常不友好,而且该方法的设计对于scala而言简直就是一道伤疤.好在scala有隐式转换,隐式参数的功能,在这个地方可以用隐式参数来减轻调用者的麻烦
object Main3 extends App {import scala.reflect.runtime.universe._def test2[A: TypeTag](_x: List[A]) = typeOf[A] match {case t if t =:= typeOf[String] => "String List"case t if t =:= typeOf[Int] => "Int List"}println(test2(List("s1", "s2")))println(test2(List(1, 2)))}
多界界定
可以同时拥有上界和下界
T >: A <: B
这种情况下界必须写在前面,上界写在后面,位置不能反.同时,A要符合B的子类型,A与B不能是两个无关的类型
可以同时拥有多个view bounds
T <% A <% B
这种情况要求必须同时存在T => A的隐式转换,和T => B的隐式转换
类型约束
类型约束,提供了限定类型的另一种方式,一共有3种声明
T =:= U意思为: T类型是否等于U类型
T <:< U意思为: T类型是否为U或U的子类型
T <%< U意思为: T类型是否被隐式(视图)转换为U
如果想使用上面的约束,需要添加”隐式类型证明参数”,比如:
class Pair5[T](_val first: T_ val second: T)(implicit ev: T <:< Comparable[T]) { }
