Scala 泛型

Scala 泛型

  • 1、泛型类和泛型函数
  • 2、泛型界定
    • ~泛型上限
    • ~泛型下限
  • 3、视图绑定
  • 4、上下文界定(绑定)
  • 5、泛型的型变

1、泛型类和泛型函数

  • 泛型类:定义类的时候,定义泛型,这个泛型就可以在类的任何地方使用
  • 泛型函数:定义函数的时候定义泛型,这个泛型只能在函数的内部使用
object Generic1 {
  def main(args: Array[String]): Unit = {
    val p1 = new Point[Int](10,20)
    val x = p1.x

    val p2 = new Point[Double](11.1,1.2)
    val y = p2.y

    val i =p1.dis(10) //它会根据x,y 自动推导
  }
}
case class Point[T](x:T,y:T){
  val z = x
  def foo():T = x
  def dis[A](a:A) = a
}

2、泛型界定

~泛型上限

case class AA(val age:Int) extends Ordered[AA]{
  override def compare(that: AA): Int = age-that.age

}
object Generic2 {
  def main(args: Array[String]): Unit = {
   val max = compare(new AA(10),new AA(20))
    println(max)
  }

  def compare[T<: Ordered[T]](x:T,y:T) = {
    if(x > y) x
    else y
  }
}

~泛型下限

class Animal{
  val name:String
}

class Pet extends Animal{
  override val name: String = _
}

class Dog extends Pet{
  override val name:String = "dog"
}

class Cat extends Pet{
  override val name:String = "cat"
}

class Lion extends Animal{
  override val name:String = "lion"
}


object LowerBound {
  def main(args: Array[String]): Unit = {
    val dog: Dog = new Dog()
    val cat: Cat = new Cat()
    val lion: Lion = new Lion()

    print(dog)
    print(cat)
    print(lion)

    print1(new Pet())
    print1(new Animal())
    print1(new Object())
    print1(dog)
    print1(1)

  }
  def print1[P >: Pet](p:P)={
    p
  }
}

3、视图绑定

object ViewBound {
  def main(args: Array[String]): Unit = {
    println(max(10,20))
    println(max("a",""))
  }

  //T <: Ordered[T] 会报错
  //T <% Ordered[T] 表示一定存在隐式转换函数,T => Ordered[T],Int => Ordered[Int]
  def max[T <% Ordered[T]](x:T,y:T)={
    if(x > y) x
    else y
  }
}
/* 等价于视图绑定的
def max[T](x:T,y:T)(implicit ev$1: T => Ordered[T])={
    if(x > y) x
    else y
  }
*/

4、上下文界定(绑定)

  • [T.Ordering],表示存在一个隐式值:Ordering[T],等价于隐式值+隐式参数
  • 需要召唤隐式值
object ContextBound {
  def main(args: Array[String]): Unit = {
    println(max(10, 20))
    println(max("10", "20"))
  }
  
  def max[T:Ordering](x:T,y:T)={
    // x < y |找一个比较器去比较 x 、y Ordering[T]
    //召唤隐式值
    val ord = implicitly[Ordering[T]]
    if(ord.gt(x,y)) x
    else y
  }
}

case class People(age:Int,name:String)
object People{
  implicit val ord:Ordering[People] = new Ordering[People](){
    override def compare(x:People,y:People):Int = x.age-y.age
  }
}
object ContextBound {
  def main(args: Array[String]): Unit = {
    println(max(10, 20))
    println(max("10", "20"))
    println(max(People(10,"a"),People(20,"b")))
  }

  def max[T:Ordering](x:T,y:T)={
    // x < y |找一个比较器去比较 x 、y Ordering[T]
    //召唤隐式值
    val ord = implicitly[Ordering[T]]
    if(ord.gt(x,y)) x
    else y
  }
}

5、泛型的型变

不变:

  • 子类型的集合对象不能赋值给父类型的集合引用
  • 默认都是不变的
  • [T]

协变:

  • 子类型的集合对象可以赋值给子类型的集合引用
  • List 有协变,Set、Array没有
  • [+T]

逆变:

  • 父类型的集合对象可以赋值给子类型的集合引用
  • 参数位置为逆变点
  • [-T]
class MyList[T] //不变

class Father
class Son extends Father

object TypeVariable {
  def main(args: Array[String]): Unit = {
    val a:Father = new Son //编译不通过

    var fList = new MyList[Father]
    var sList = new MyList[Son]
    fList = sList  //编译不通过
  }
}
class MyList[+T] {//表示协变
//	def foo(t:T) ={} 报错 参数位置为逆变点
	def foo():T = t  //协变类型可以放在返回值位置
}
class Father
class Son extends Father

object TypeVariable {
  def main(args: Array[String]): Unit = {
    val a:Father = new Son

    var fList = new MyList[Father]
    var sList = new MyList[Son]
    fList = sList  //编译通过
  }
}
//集合
class MyList[-T] {//逆变
	def foo(t:T) ={} //可以
//	def foo():T = t  报错,逆变类型出现在协变位置
	def foo[A <: T](a:A):A = a //可以通过加上界解决
} 

class Father
class Son extends Father

object TypeVariable {
  def main(args: Array[String]): Unit = {
    val a:Father = new Son

   val sList = new MyList[Father]
  }
}

你可能感兴趣的:(Scala,基础内容)