Scala入门到放弃——泛型(十)

十四、泛型

泛型类

类似于Java,类和特质可以携带类型参数

class Student[T, S](var name: T, var age: S) {   // T S K 
												 // <> ---> [T,S,K]
}

object Student {
  def main(args: Array[String]): Unit = {
    // 创建类时,手动指定泛型类型
    val stu = new Student[String, Int]("zs", 18)
    println(stu.name + "\t" + stu.age)

    // 采用自动推断
    val stu2= new Student("zs", 18)
    println(stu2.name + "\t" + stu2.age)
  }
}

泛型方法和函数

函数和方法也可以带类型参数

def format[T](x: Array[T]) = {  //类型参数放在方法名之后
  println(x.mkString(","))
}

def format2[T](x: Array[T]): Array[String] = {
  x.map(_ + "")
}

// 调用时,手动指定泛型类型
format[Int](Array(1, 2, 3, 4))
// 或
format(Array(1, 2, 3, 4))

println(format2(Array[Int](1,2,3,4)).mkString("|"))
返回值泛型需要根据传入参数动态改变

上边界

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

trait Animals

class Dog extends Animals

class Keeper[U <: Animals] {  // 表示Keeper的实现类只能饲养Animal以及Animal的子类
  def keep(a: U): Unit = {
    println("饲养动物:"+a.getClass)
  }
}
object Keeper {
  def main(args: Array[String]): Unit = {
    val dog = new Dog
    new Keeper[Dog]().keep(dog)
  }
}

下边界

语法:[T >: s] ,限定T类型必须S的父类型

class Animals

class Dog extends Animals

class Car

class Keeper2[T >: Dog] {   // 表示Keeper的实现类只能饲养Dog或者Dog的父类
  def keeper(d: T) {
    println("饲养狗的同类..." + d.getClass)
  }
}

object Keeper2 {
  def main(args: Array[String]): Unit = {
    new Keeper2[Dog].keeper(new Dog)
    new Keeper2[Animals].keeper(new Animals)
    new Keeper2[Car]  //error
  }
}

下边界范围:包含父类 间接父类和本身

视图限定

语法:[T <% S], 运行时尝试将T类型隐式转换为S类型

package generic.viewlimit

import java.text.SimpleDateFormat
import java.util.Date

/**
  * 视图限定  尝试通过隐式转换将T 类型转换Date类型
  *
  * @param  first 传进来的是字符串
  *
  */
class Convert[T <% Date](val first: T) {
  def print() = {
    println(first.toLocaleString)
  }
}

object Convert {
  // 定义隐式转换函数
  implicit def str2Date(str:String):Date = {
    new SimpleDateFormat("yyyy-MM-dd").parse(str)
  }

  def main(args: Array[String]): Unit = {
    val c1 = new Convert[String]("2018-10-10")
    c1.print()
  }
}

上下文限定

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

package generic

/**
  * 1) 要求:使用上下文界定+隐式值的方式,比较两个Person对象的年龄大小
  * 2) 要求:使用Ordering实现比较
  */
class Person(var name: String, var age: Int)

object Person {
  //1. 声明一个隐式值
  implicit val ordering: Ordering[Person] = new Ordering[Person]() {
    /**
      * 比较大小的方法
      *
      * @param x
      * @param y
      * @return 1  大于  -1 小于
      */
    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", 10)
    val p2 = new Person("ls", 100)

    val tools = new CompareUtils[Person](p1, p2)

    if (tools.comparable() == 1) {
      println("大于")
    } else {
      println("小于")
    }
  }
}

// 上下文限定 T:M  M必须是一个泛型类  M[S]泛型类必须得有个隐式值
class CompareUtils[T: Ordering](p1: T, p2: T) {

  def comparable() = {
    // 获取隐式值
    val tools = implicitly[Ordering[T]]

    tools.compare(p1, p2)
  }
}

多重限定

A和B为T上界
class A

class B extends A

class C extends B

/*
trait A

trait B

class C extends B with A // 动态混入
*/

// 多重 上边界  T类型必须同时是A和B类型的子类型【并且】
class E[T <: A with B](t:T)

object E{
  def main(args: Array[String]): Unit = {
    val e1 = new E[C](new C)
  }
}
A和B为T下界
class A

class B extends A

class C

class D extends C

class E[T >: B with D](t: T) // T 类性是B类性或C类型父类型

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

    val e1 = new E[A](new A) // ok

    val e2 = new E[B](new B) // ok
    val e3 = new E[C](new C) // ok

    val e4 = new E[D](new D) //OK
  }
}
同时拥有上界和下界,并且A为下界,B为上界,A为B的子类,顺序不能颠倒
class A

class B extends A

class C extends B


class D[T >: C <: A](t: T)

object D {
  def main(args: Array[String]): Unit = {
    val d = new D[B](new B)
  }
}
视图界定,即同时能够满足隐式转换的A和隐式转换的B (略)
def say[T <% A <% B](v:T):Unit={
  println(v)
}
trait A{}
trait B{}
+A 协变 [+T]

C[T1]是 C[T]的子类

// dog[T1] 是 animals [T]子类
// Convariant[T1] ---> Convariant[T] 的子类

class Animals

class Dog extends Animals

class A[+T]

object Dog {
  def main(args: Array[String]): Unit = {
    // 协变
    val a = new A[Dog]()

    val a2: A[Animals] = a  // 父子关系 A[Dog] extends A[Animals]
  }
}

// java
// Dog ---> Animals
// List<Dog> ---> List<Animals>
-A 逆变 [-T]

C[T] 是 C[T1]的子类

class Covariant[-T](t:T){}
val cov = new Covariant[Animal](new Animal("动物"))
val cov2:Covariant[Dog] = cov
A 不变 [T]

C[T] 与 C[T1]不相关

class Animals2

class Dog2 extends Animals2

class A2[-T]

object Dog2 {
  def main(args: Array[String]): Unit = {
    // 逆变
    val a = new A2[Animals2]()

    val a2: A2[Dog2] = a // 父子关系  A[Animals]  extends A[Dog]
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值