视图界定 <%
<% 有隐式转换
package com.doit.scala.yinshizhuanhuan
/* [T <: Comparable[T]] 上界 upper bound java: <T extends Comparable>
* [T >: Comparable[T]] 下界 lower bound java: <T super Comparable>
* [T <% Comparable] 视图界定 view bound 跟隐式转换有关的
* [T : Comparable] 上下文界定 context bound 跟隐式转换有关的
* [-T] 逆变 方法输入参数
* [+T] 协变 方法返回
* */
class Pair1[T <% Comparable[T]] {
def bigger(first: T,second:T):T={
if(first.compareTo(second)>=0)first else second
}
}
object Pair1{
def main(args: Array[String]): Unit = {
//首先,先用Int类型举个例子
//Int并没有实现Comparable接口没有compare方法的,
// 如果是<: 就不能实现下面方法
//<% 就能够实现以下方法 因为<% 有隐式转换
// 在Ordering中有隐式转换
val p1 = new Pair1[String]
val i = p1.bigger("hl", "xg")
println(i)
}
}
上界 upper bound
在设定上界中,不需要implicit方法,只需要在需要比较的类中继承Ordered,添加上泛型,然后重写compare方法
package com.doit.scala.yinshizhuanhuan
import com.doit.scala.day05.Girl
class Pair2 [T <: Ordered[T]]{
//Scala中用于比较的两个类:Ordered、Ordering
//Ordered 实现了java.lang.Comparable接口,对Comparable进行了扩展,更灵活,用气量更方便
//Ordering 实现了java的 Comparator接口,同时对Comparator进行了扩展
def select(first: T,second: T): T={
if(first >= second) first else second
}
}
object Pair2{
def main(args: Array[String]): Unit = {
val girl = new Pair2[Girl]
val zh = new Girl("zh", 99)
val qj = new Girl("qj", 59)
println(girl.select(zh,qj).name)
}
}
package com.doit.scala.day05
class Girl(val name: String,val fv: Double) extends Ordered[Girl]{
override def compare(that: Girl): Int =
(this.fv-that.fv).toInt//降序
}
视图界定 view bound
如果传入的泛型 是视图界定的 但是并没有在类中或者方法中定义比较方法,就需要在 new出比较方法实例的之前将 implicit导进来,传进来的 implicit可以是函数,也可以是方法,优先导入函数,如果没有函数就将方法转换成函数导入
package com.doit.scala.yinshizhuanhuan
import com.doit.scala.day05.Boy
class Pair3[T <% Ordered[T]] {
def choose (first: T,second: T):T ={
if(first > second)first else second
}
}
object Prir3{
def main(args: Array[String]): Unit = {
import ContextDemo._
val p3 = new Pair3[Boy]
val hulei = new Boy("hulei", 2)
val caojianxi = new Boy("caojianxi", 100000)
val boy = p3.choose(hulei, caojianxi)
println(boy.name)
}
}
package com.doit.scala.yinshizhuanhuan
class Boy (val name: String,val fv: Int){
}
implicit def Boy2(boy: Boy):Ordered[Boy]=new Ordered[Boy] {
override def compare(that: Boy): Int = {
(boy.fv-that.fv).toInt
}
上下文界定 context bound
相当于直接将泛型准确的锁定在对应类上
需要传入一个隐式类型 类 而不是方法或者函数
package com.doit.scala.yinshizhuanhuan
//context bound 上下文界定,就是实现隐式转换
//上下文界定 需要传入一个隐式类型 类
class Pair4 [T : Ordering]{
def bigger (first :T,second: T):T={
val ord: Ordering[T] = implicitly[Ordering[T]] //本来是毫无关系的T 和 Ordering的两个类 需要用implicitly方法 使两个类关联起来
if(ord.gteq(first,second))first else second
}
}
object Pair4{
def main(args: Array[String]): Unit = {
import ContextDemo._
// val p4 = new Pair4[Man]
// val hulei = new Man("hulei", 78)
// val caojianxi = new Man("caojianxi", 18)
// println(p4.bigger(hulei,caojianxi).name) //hulei
// //明明需要Ordering[Man]类型的参数,但是你给的是Ordered[Man]的函数或方法
// //说明幕后有一个神奇的力量,可以将Ordering[T]转成Ordered[T]
val p4 = new Pair4[Man]
val hulei = new Man("hulei", 78)
val caojianxi = new Man("caojianxi", 18)
println(p4.bigger(hulei,caojianxi).name)
}
}
package com.doit.scala.yinshizhuanhuan
class Man(val name:String,val age:Int) {
implicit object ManOrdering extends Ordering[Man]{
override def compare(x: Man, y: Man): Int = {
x.age-y.age
}
}
}
以上的代码都是即将淘汰的方法,下面是两种新方法
package com.doit.scala.yinshizhuanhuan
//既不使用视图界定,也不实用上下文界定,但是要实现跟视图界定和上下文界定一样的功能
//视图界定:隐式转换函数或方法
//上下文界定:隐式转换类型
class Pari5[T] {
//使用柯里化,实现类似视图界定的功能
def bigger(first: T,second: T)(implicit f:T => Ordered[T]):T = {
if(first>=second)first else second
}
//使用柯里化,实现类似上下文界定的功能
def select(first: T,second: T)(implicit ord: Ordering[T]):T = {
if(ord.gteq(first,second))first else second
}
}
object Pari5{
def main(args: Array[String]): Unit = {
import ContextDemo._
// val p5 = new Pari5[Boy]
// val hulei = new Boy("hulei", 2)
// val caojianxi = new Boy("caojianxi", 100000)
// val boy = p5.bigger(hulei, caojianxi)
// println(boy.name)
val p = new Pari5[Man]
val b1 = new Man("A", 88)
val b2 = new Man("B", 99)
val r = p.bigger(b1, b2)
println(r.name)
}
}