Scala 类型参数

类型参数主要就是研究scala当中的类或者scala当中的方法的泛型

1.类的泛型

object Scala01_Demo01 {
  def main(args: Array[String]): Unit = {
    val result1 = new MyClass("hello",50)
    val result2 = new MyClass[Any,Any]("zhangsan","Lisi");
  }
}

/**
 * 定义一个class类,接收两个参数,但是两个参数都是泛型,泛型的类型,会根据我们创建类的实例化对象的时候,动态的传递进行动态的推断
 */
class MyClass[T,B](first:T,second:B){
  println(first+","+second)
}

2.函数的泛型

object Scala02_methodType {
  def getMiddle[T](canshu:T) ={
    canshu
  }
  def main(args: Array[String]): Unit = {
    // 从参数类型来推断类型
    println(getMiddle(Array("Bob", "had", "a", "little", "brother")).getClass.getTypeName)
    //指定类型,并保存为具体的函数。
    val f = getMiddle[String] _
    println(f("Bob"))
  }
}

3.scala当中的上下界之泛型类型的限定

  • 在scala当中,我们可以通过上界或者下界来限定我们泛型的类型,类似于java当中的

  • ? extends T ?号就表示我们使用的泛型,必须是T类型的子类,这种情况叫做上界

  • ? super T ?号就表示我们使用的泛型,必须是T类型的父类,这种情况叫做下界

  • 在scala当中上界的表示方法使用的是 "<:", 这个符号就是表示上界,这种形式称之为泛型的上界。

  • 在scala当中下界的表示方式使用的是 ">:", 这个符号就是表示下界,这种形式称之为泛型的下界。

3.1 泛型的上界限定

class Pair1[T <: Comparable[T]](val first: T, val second: T) {
  def smaller = if (first.compareTo(second) < 0) first else second
}
//我们可以通过上界的限定,限定我们传入的类型必须是某个类型的子类
object Scala03_Main1  extends App{
    override def main(args: Array[String]): Unit = {
      val p = new Pair1("hello", "Brooks")
      println(p.smaller)
    }
}

3.2 泛型的下界限定

class Pair2[T](val first: T, val second: T) {
  def replaceFirst[R >: T](newFirst: R) = new Pair2[R](newFirst, second)
  override def toString = "(" + first + "," + second + ")"
}
//我们可以通过下界的限定,限定我们传入的类型必须是某个类型的父类
object Scala03_Main2  extends App{
    override def main(args: Array[String]): Unit = {
      val p = new Pair2("Nick", "Alice")
      println(p)
      println(p.replaceFirst("Joke"))
      println(p)
    }
}

在Java中,T同时是A和B的子类型,称之为多界,形式如:<T extends A & B>。

  • 在Scala中,对上界和下界不能有多个,但是可以使用混合类型,如:[T <: A with B]。

  • 在Java中,不支持下界的多界形式。如:<T super A & B>这是不支持的。

  • 在Scala中,对复合类型依然可以使用下界,如:[T >: A with B]。

 

4.视图界定

    说白了就是将我们的泛型转化成了具体的类型

    在Scala中,如果你想标记某一个泛型可以隐式的转换为另一个泛型,可以使用:[T <% Comparable[T]],由于Scala的Int类型没有实现Comparable接口,所以我们需要将Int类型隐式的转换为RichInt类型,比如:

    我们如果需要比较两个值的大小,那么我们的两个值必须是Comparable的子类,那么我们可以使用泛型 T <% Comparable 来限制我们泛型必须是Comparable的子类,并且我们的泛型在执行真正比较的方法的时候,会根据我们传入的类型,自动推断,进行隐式的转换,例如我们传入4,2 进行比较,那么我们会将4, 2 这两个类型做自动推断,转换成真正的RichInt类型然后再继续进行比较

class Pair3[T <% Comparable[T]](val first: T, val second: T) {
  def smaller = if (first.compareTo(second) < 0) first else second
  override def toString = "(" + first + "," + second + ")"
}


object Scala04_Main3  extends App {
    val p = new Pair3(4, 2)
    println(p.smaller)
}

5.Scala当中协变,逆变和非变

    协变和逆变主要是用来解决参数化类型的泛化问题。Scala的协变与逆变是非常有特色的,完全解决了Java中泛型的一大缺憾;举例来说,Java中,如果有 A是 B的子类,但 Card[A] 却不是 Card[B] 的子类;而 Scala 中,只要灵活使用协变与逆变,就可以解决此类 Java 泛型问题;

    由于参数化类型的参数(参数类型)是可变的,当两个参数化类型的参数是继承关系(可泛化),那被参数化的类型是否也可以泛化呢?Java中这种情况下是不可泛化的,然而Scala提供了三个选择,即协变("+")、逆变("-")和非变。

    下面说一下三种情况的含义,首先假设有参数化特征Queue,那它可以有如下三种定义。

class Super
class Sub extends Super

//协变
class Temp1[+A](title: String)

//逆变
class Temp2[-A](title: String)

//非变
class Temp3[A](title: String)

object Scala05_Covariance {
    def main(args: Array[String]) {

      //支持协变 Temp1[Sub]还是Temp1[Super]的子类
      val t1: Temp1[Super] = new Temp1[Sub]("hello scala!!!")

      //支持逆变 Temp1[Super]是Temp1[Sub]的子类
      val t2: Temp2[Sub] = new Temp2[Super]("hello scala!!!")

      //支持非变 Temp3[Super]与Temp3[Sub]没有从属关系,如下代码会报错
      //val t3: Temp3[Sub] = new Temp3[Super]("hello scala!!!")
      //val t4: Temp3[Super] = new Temp3[Sub]("hello scala!!!")
      println(t1.toString)
      println(t2.toString)
    }
}

   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员学习圈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值