Scala 泛型 (十)

泛型

  • 安全:将运行时期可能出现类型错误转换到了编译期
  • 避免类型转换
List list = new ArrayList();
list.add("aa")
list.add(10)

Object obj = list.get(0);

Java泛型回顾

  1. 泛型类
  2. 泛型方法
  3. 上边界
  4. 下边界
  5. 无固定边界
// 1. 泛型类
// 2. 泛型方法
// 3. 上边界
// 4. 下边界
// 5. 无固定边界
package generic.java;

import scala.actors.threadpool.Arrays;

import java.util.ArrayList;
import java.util.List;

/**
 * java 泛型学习
 */
public class GenericTest {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("aa");
        list.add(10);
        String aa = (String) list.get(0);
        System.out.println(aa);

        List<String> list2 = new ArrayList<String>();
        list2.add("aa");
        String aa2 = list2.get(0);
        System.out.println(aa2);

        A<String, Integer, Double> a1 = new A<String, Integer, Double>();
        a1.setT("zs");
        String name = a1.getT();
        System.out.println(name);

        a1.m1(10.0);
        a1.m1(10L);
        a1.m1(3.14F);

        ArrayList<C> list3 = new ArrayList<C>();
        ArrayList<B> list4 = new ArrayList<B>();
        ArrayList<String> list5 = new ArrayList<String>();

        a1.m2(list3);
        a1.m2(list4);
        // a1.m2(list5); //error

        ArrayList<C> list6 = new ArrayList<C>();
        ArrayList<B> list7 = new ArrayList<B>();
        ArrayList<String> list8 = new ArrayList<String>();
        a1.m3(list6);
        a1.m3(list7);

        ArrayList<C> list9 = new ArrayList<C>();
        ArrayList<B> list10 = new ArrayList<B>();
        ArrayList<String> list11 = new ArrayList<String>();
        a1.m4(list9);
        a1.m4(list10);
        a1.m4(list11);
    }
}

// 泛型类
class A<T, S, K> {
    private T t;
    private S s;
    private K k;

    // 泛型方法 M类型必须是Number类型的子类型
    public <M extends Number> void m1(M m) {
        System.out.println(m);
    }

    // 上边界  必须为B类型的子类
    public void m2(List<? extends B> list) {
        list.forEach(n -> System.out.println(n));
    }

    // 下边界 ? 类型必须是C类型的父类型
    public void m3(List<? super C> list){
        list.forEach(n-> System.out.println(n));
    }

    // 无固定边界 泛型无固定
    public void m4(List<?> list){
        list.forEach(n-> System.out.println(n));
    }

    public T getT() {
        return this.t;
    }

    public void setT(T t) {
        this.t = t;
    }
}

class B {

}

class C extends B {

}

Scala 泛型类

语法: 类名[泛型类型,....]

package generic
/**
  * 泛型类
  */
object GenericClass {

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

    var a: A[String] = new A[String]
    val t = a.t  //null
    println(t)
    val b = new B[String,Double,Int]("ABC",90,90)
    println(b) // ABC	90.0	90

  }
}

class A[T]{
  var t: T = _
}
// 泛型类
class B[T,M,N](t:T,m:M,n: N){

  override def toString: String = t + "\t" + m + "\t" + n

}

Scala 泛型方法

约束方法中的形参类型

package generic.scala

import scala.collection.mutable

object GenericMethod {
  def main(args: Array[String]): Unit = {
    print[String](Array("abc", "efg", "xyz"))
    print(Array("abc", "efg", "xyz"))
    print(Array[Any]("abc", "efg", "xyz", 10)) //OK
    // print(Array[String]("abc", "efg", "xyz",10)) //ERROR

    ret[String](Array("abc", "efg", "xyz"))
  }

  /**
    * 泛型方法
    *
    * @param arr
    * @tparam K
    */
  def print[K](arr: Array[K]): Unit = {
    arr.foreach(println)
  }

  def ret[M](arr: Array[M]): mutable.Buffer[M] = {
    arr.toBuffer
  }
}

上边界&下边界

上边界: 语法:[T <: S] ,T类型必须是S类型的子类型,包含S类型本身

下边界: 语法:[T >: S] ,T类型必须是S类型的父类型,包含S类型本身

package generic

/**
  * 上边界 和 下边界
  *
  */
object GenericUpperAndLowerBound {

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

    val b1 = new Cc[Bb]
    val b2 = new Cc[Aa]

//    val  b3 = new Cc[Dd]  // error


    val a1 = new Ee[Aa]
    val a2 = new Ee[Ff]
//    val a3 = new Ee[Bb]  // error


  }

}

class Aa extends Ff

class Bb extends Aa
// 上边界,K为Aa的子类
class Cc[K <: Aa]{

}

class Dd

// 下边界,k为Aa的父类
class Ee[K >: Aa]

class Ff

视图边界

语法:[T <% S], 运行时尝试将T类型隐式转换为S类型,要求当前类或者作用域存在隐式转换;

package generic.view

import java.text.SimpleDateFormat

import scala.collection.mutable

/**
  * 视图边界
  *   将泛型转为定义的类型,需要存在一个隐式转换
  */
object ViewBound {

  def main(args: Array[String]): Unit = {
    val a = new A[String]("2020-01-01 13:00:01")
    a.printDate()
  }

    // string 转为 Date 的隐式转换器
  implicit def stringToDate(date: String): java.util.Date ={

    val format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    format.parse(date)
  }

}
// 泛型转为 Date 类型
class A[K <% java.util.Date](k: K){

  def printDate(): Unit ={

    val date = new java.util.Date(k.getTime) // 使用时间戳 创建出一个日期对象
    val format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") // 格式化日期对象
    println(format.format(date))
  }
}

class Animal{
  def eat(): Unit ={
    println("Animal is eating")
  }
}

// ----------- 视图边界 ------------
class Dog

class S[k <% Animal]

object Dd extends App{

  var value = new S[Dog]
  value.eat()

  // 隐式转换  泛型
  implicit def dogToAnimal(dog: Dog): Animal={
    new Animal
  }

  // 隐式转换  S[Dog] 类型 转为Animal类型
  implicit def sToAnimal(s:S[Dog]): Animal = {
    new Animal
  }

}

多重限定

多重上界

语法:[T <: S with K] 表示T类型必须同时是S类型和K类型的子类型

多重下界

语法:[T >: S with K] 表示T类型必须S类型或者K类型的父类型

多重上界需要同时为泛型的子类
下界满足一个父类

package generic.multi

/**
  * 多重上界 多重下界
  */
object GeneriUpper {

  def main(args: Array[String]): Unit = {
    val z1 = new Z[C]
    val z2 = new Z[B]
//    val z3 = new Z[A]  // error

    val x1 = new X[Y]
    val x2 = new X[A]
    val x3 = new X[B]
    val x4 = new X[C]

  }

}

class Y

class A extends Y

class B extends A

class C extends B

// 泛型必须为B和A的子类型
class Z[T <: B with A]

// 泛型必须为 B或者C的父类
class X[T >: B with C]

既有上界又有下界

语法:[T >: S <: K] 表示T类型的上边界为K类型,下边界为S类型

package generic.multi

/**
  * 既有上界  又有下界
  * 语法:`[T >: S <: K]` 表示T类型的上边界为K类型,下边界为S类型
  */

object MutiUpperBound {

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

    val c1 = new CC[DD]
    val c2 = new CC[BB]
    val c3 = new CC[AA]
   // val c4 = new CC[EE]  // error

  }

}

class AA

class BB extends AA

class DD extends BB

class EE extends DD
// T类型必须是DD类型的父类型,AA类型的子类型 包含上下界本身
class CC[T >: DD <: AA]

协变

语法:[+T]

如果T类型是T1类型的父类型,则 C[T]类型是C[T1]类型的父类
泛型为父子关系,使用泛型后也为父子关系

package generic.xb

/**
  * 协变
  * 语法:`[+T]`
  *
  * 如果T类型是T1类型的父类型,则 C[T]类型是C[T1]类型的父类
  */
object GenericXB {

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

    val c1 = new C[B]

    val c2: C[A] = c1

  }

}

class A

class B extends A
// 泛型A 的父类是B  那么C[A]就是C[B]的父类
class C[+T]

逆变

语法:[-T]

如果T类型是T1类型的父类型,则C[T]类型是C[T1]类型的子类型
父子关系逆向

package generic.nb

/**
  * 逆变
  * 语法:[-T]
  *
  * 如果T类型是T1类型的父类型,则C[T]类型是C[T1]类型的子类型
  */
object GenericNB {

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

    val x1 = new X[A]

    val x2: X[B] = x1


  }

}

class A

class B extends A
// 泛型A 的父类是B  那么C[B]就是C[A]的父类
class X[-T]

不变

语法:[T]
使用泛型后不改变任何属性

上下文限定(拓展)

语法:[T:M] 上下文界定的形式为T:M,其中M是另一个泛型类,它要求必须存在一个类型为M[T]的隐式值。

implicit val  ordering:Ordering[Person] = new Ordering(){}

[T:Ordering] 

implicitly[Ordering[T]]
package generic.scala.contextbound

// 语法:`[T:M]`
//
//    上下文界定的形式为T:M,其中M是另一个泛型类,它要求必须存在一个类型为M[T]的隐式值。
class Person(var name: String, var age: Int)

object Person {
  // 声明ordering[Person]的隐式值【对象】
  implicit val ordering: Ordering[Person] = new Ordering[Person] {
    override def compare(x: Person, y: Person): Int = if (x.age > y.age) 1 else -1
  }

  def main(args: Array[String]): Unit = {
    val p1 = new Person("zs", 20)
    val p2 = new Person("ls", 30)
    val tools = new CompareUtils[Person](p1, p2)
    if(tools.compare == 1){
      println("大于")
    }else{
      println("小于")
    }
  }
}

/**
  * T: 泛型类(Ordering)
  *
  *   T:M  M必须是泛型类,并且必须提供同类型的隐式值
  *
  * @tparam T
  */
class CompareUtils[T: Ordering](p1: T, p2: T) {

  def compare: Int = {
    val ordering = implicitly[Ordering[T]] // 获取一个Ordering[T]隐式值
    ordering.compare(p1,p2)
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值