scala的泛型

  1. 基本概念

    • Scala 中的泛型允许我们编写可以处理多种不同类型数据的代码,就像在 Java 等其他语言中一样。泛型通过类型参数来实现,它使得我们能够创建通用的类、方法和特质(trait)。
    • 例如,定义一个简单的泛型类Box,它可以用来存储任何类型的值:
    Scala 复制代码
       class Box[T](content: T) {
           def getContent(): T = content
       }
  • 在这里,T是一个类型参数。我们可以用任何具体的类型来替换T,比如Box[Int]可以存储整数,Box[String]可以存储字符串。
  1. 类型参数约束
    • 有时候我们希望对类型参数进行一些限制。例如,我们可能希望类型参数是某个类的子类或者实现了某个特质。这可以通过<:(上界)或>:(下界)符号来实现。
    • 上界约束:假设我们有一个类层次结构,Animal是基类,CatDogAnimal的子类。我们定义一个函数,它只能处理Animal及其子类的列表。
  • 在这个例子中,AnimalSubtype是一个类型参数,它的上界是Animal。这意味着AnimalSubtype可以是Animal本身或者它的任何子类。
  • 下界约束:相对较少使用,但在某些场景下很有用。例如,当我们想要处理一个函数,它接受一个类型参数,并且这个类型参数是某个类型的超类时。
Scala 复制代码
   class Animal
   class Cat extends Animal
   class Dog extends Animal
   def printAnimalNames[AnimalSubtype <: Animal](animals: List[AnimalSubtype]) {
       animals.foreach(animal => println(animal.getClass.getName))
   }
   val cats: List[Cat] = List(new Cat, new Cat)
   printAnimalNames(cats)
  • 这里T的下界是Cat,所以T可以是Cat或者它的超类。
  1. 协变和逆变
    • 协变(Covariance):如果AB的子类型,那么List[A]也是List[B]的子类型,这种性质称为协变。在 Scala 中,我们可以使用+符号来标记协变的类型参数。
  • 逆变(Contravariance):与协变相反,如果AB的子类型,那么Function1[B, C]Function1[A, C]的子类型。在 Scala 中,用-符号标记逆变的类型参数。
  1. 泛型方法
    • 除了泛型类,Scala 还支持泛型方法。泛型方法是一种独立于类的泛型定义方式。
  • 这个identity方法可以接受任何类型的参数,并返回相同类型的结果。类型参数T在方法定义时确定,根据传入的实际参数类型来推断。
  1. 存在类型(Existential Types)

    • 存在类型用于表示存在某个满足特定条件的类型。
    Scala 复制代码
    package test40
    
    //泛型
    //需求:你是一个程序员,老板让你写一个函数,用来获取列表中的中间元素
    //List(1,2,3,4,5) ==> 中间元素下标 = 长度/2 ====> 3
    //getMiddleEle
    //[T]就是泛型:类型参数化,把类型当作参数传入函数内部
    object test {
      //定义函数的格式
      //def 函数名字(参数1,参数2):返回值类型={
      // }
    //  def getMiddleEle1(list:List[Int]):Int=list(list.length/2)
    //
    //  def getMiddleEle2(list: List[String]): String = list(list.length / 2)
    //
    //  def getMiddleEle3(list: List[Double]): Double = list(list.length / 2)
      def getMiddleEle[T](list: List[T]):T = list(list.length/2)
    
    
      def main(args: Array[String]): Unit = {
        val rs1 = getMiddleEle[Int](List(1,2,3,4,5))
        println(rs1)//3
    
        val rs2 = getMiddleEle[String](List("1","2","C","4","5"))
        println(rs2) //c
    
        println(getMiddleEle[Double](List(1.2,2.0,2.9)))
    //    println(rs2) //c
    //    println(1)
    //    println(2)
    //    println(3)
    //    println(getMiddleEle1(List(1,2,3,4,5)))//3
    //
    //    println(getMiddleEle2(List("1","2","C","4","5")))
    //
    //    println(getMiddleEle3(List(1.2,2.0,2.9)))//2.0
      }
    
    }
相关推荐
飞由于度24 分钟前
C#编程报错- “ComboBox”是“...ComboBox”和“...ComboBox”之间的不明确的引用
开发语言·c#
阿芯爱编程1 小时前
最大子数组的值
后端·算法·面试
Invulnerabl_DL1 小时前
C++ STL学习
开发语言·c++·学习·stl
steamedobun1 小时前
【爬虫】selenium打开浏览器以及页面
开发语言·python·selenium
智慧老师1 小时前
数据结构第一弹-数据结构在不同领域的应用
开发语言·数据结构·python
caifox2 小时前
C# 探险之旅:第十四节 - 函数介绍
开发语言·c#
zi__you3 小时前
【Python网络爬虫 常见问题汇总】
开发语言·爬虫·python
水w3 小时前
微服务之间的相互调用的几种常见实现方式对比 2
java·开发语言·后端·微服务·架构
梧桐树04293 小时前
python面向对象高级编程:使用@property
开发语言·python
潘多编程3 小时前
SpringBoot 3.2:CRaC技术助力启动速度飞跃
java·spring boot·后端