Scala泛型

/**
 * [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] 协变   方法返回
 */

上下界定

上界:   [T <: Comparable[T]]            相当于java: <T extends Comparable>
下界:   [T >: Comparable[T]]            相当于java: <T super Comparable>

栗子:

定义一个类,指定泛型是Comparable接口的子类

class Pair[T <: Comparable[T]] {

  def bigger(t1:T ,t2: T):T = {
   if(t1.compareTo(t2) > 0) t1 else t2
  }

}

测试:创建实例指定泛型为java.lang.Integer,该类实现了Comparable接口

  def main(args: Array[String]): Unit = {
    val p1: Pair[Integer] = new Pair[Integer]  //java.lang.Integer
    val res: Integer = p1.bigger(2,5)
    println(res)   //输出5
  }

注意:如果实例定义的是scala的int类型,编译通过,但运行时报错,因为int没有实现Comparable接口,说明上下界不支持隐式转换,如果要支持隐式转换,用下例中的视图界,scala中默认隐式转换中定义了将int转换为java.lang.Integer

 

视图界定

[T <% Comparable]     跟隐式转换有关的,可以结合隐式方法或函数使用,优先使用函数

栗子:

定义一个泛型类,指定是Ordered的子类

class Pair2[T <% Ordered[T]] {
  //Scala中用于比较的两个类:Ordered、Ordering
  //Ordered 实现了java.lang.Comparable接口,对Comparable进行了扩展,更灵活,用起来更方便
  //Ordering 实现了java的 Comparator接口,同时对Comparator进行了扩展

  def selectMax(t1: T, t2: T):T = {
    if(t1 >= t2 ) t1 else t2
  }

}

 实体类,用于比较

class Product(val name: String,var price: Int) {

}

测试:

  def main(args: Array[String]): Unit = {
    val pair = new Pair2[Product]
    val p1 = new Product("p1",20)
    val p2 = new Product("p2",20)
    val product = pair.selectMax(p1,p2)
    println(product.name)
  }

输出报错:

可以看出:需要将实体类转换为Order的子类才能比较
第一种方法:可以让实体类继承Ordered特质(上下界)
第二种方法:隐式的定义一个方法将实体类转换为Ordered类(视图界),以下使用第二种方法

隐式的定义一个转换方法:

object MyContext{

  implicit  def transOrdered(p: Product): Ordered[Product] = {
    new Ordered[Product] {
      override def compare(that: Product): Int = {
            p.price - that.price
      }
    }
  }

}

导入隐式方法并测试:

  def main(args: Array[String]): Unit = {
    import MyContext.transOrdered  //在实例化前导入
    val pair = new Pair2[Product]
    val p1 = new Product("p1",20)
    val p2 = new Product("p2",20)
    val product = pair.selectMax(p1,p2)
    println(product.name)    //成功输出p1
  }

 

上下文界定

[T : Comparable]       跟隐式转换有关的,结合隐式类使用

栗子:

泛型类

class Pair3[T: Ordering] {

  def selectMax(first: T, second: T): T = {
    val ord: Ordering[T] = implicitly[Ordering[T]]  // 比较器
    if (ord.gteq(first, second)) first else second
  }

}

隐式类:定义在一个类里面

object MyContext {

  implicit object OrderingProduct extends Ordering[Product] {
    override def compare(x: Product, y: Product): Int = {
      x.price - y.price
    }
  }

} 

测试:

  def main(args: Array[String]): Unit = {
    import MyContext.OrderingProduct  //导入隐式类
    val pair = new Pair3[Product]
    val p1 = new Product("p1",20)
    val p2 = new Product("p2",10)
    val product = pair.selectMax(p1,p2)
    print(product.name)        //成功输出p1
  }

 

扩展:使用柯里化实现视图界定与上下文界定类似的功能

package com.yege.fanxing

class Pair4[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 Pair4{

  def main(args: Array[String]): Unit = {

        val p = new Pair4[Product]
        val b1 = new Product("A", 88)
        val b2 = new Product("B", 99)
        import MyContext._
        val r1 = p.bigger(b1, b2)
        val r2 = p.select(b1, b2)
        print(r1.name)
        print(r2.name)

  }

}

 

 

 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页