scala的泛型

  1. 基本概念

    • Scala 中的泛型允许我们编写可以处理多种不同类型数据的代码,就像在 Java 等其他语言中一样。泛型通过类型参数来实现,它使得我们能够创建通用的类、方法和特质(trait)。
    • 例如,定义一个简单的泛型类Box,它可以用来存储任何类型的值:
    Scala 复制代码
       class Box[T](content: T) {
           def getContent(): T = content
       }
  • 在这里,T是一个类型参数。我们可以用任何具体的类型来替换T,比如Box[Int]可以存储整数,Box[String]可以存储字符串。
  1. 类型参数约束
    • 有时候我们希望对类型参数进行一些限制。例如,我们可能希望类型参数是某个类的子类或者实现了某个特质。这可以通过<:(上界)或>:(下界)符号来实现。
    • 上界约束:假设我们有一个类层次结构,Animal是基类,Cat和Dog是Animal的子类。我们定义一个函数,它只能处理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):如果A是B的子类型,那么List[A]也是List[B]的子类型,这种性质称为协变。在 Scala 中,我们可以使用+符号来标记协变的类型参数。
  • 逆变(Contravariance):与协变相反,如果A是B的子类型,那么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
      }
    
    }
相关推荐
starzy199036 分钟前
Scala循环与判断:一切皆表达式的控制流
开发语言·人工智能·scala
starzy19901 小时前
Scala类和对象:从构造器到样例类的完整指南
开发语言·后端·scala
梦影_1 小时前
MySQL进阶教程(五)—— SQL调优(下)
android·大数据·数据库·后端·sql·mysql·database
考虑考虑1 小时前
mariadb数据库
数据库·后端·mariadb
niucloud-admin1 小时前
NIUCLOUD PHP SAAS上门家政使用文档--服务订单:订单列表
开发语言·php
明月_清风1 小时前
用自然语言操控真机:Google Artemis 移动端 AI Agent 上手与实践
人工智能·后端
怪我冷i1 小时前
Rust 的impl语法详解
开发语言·后端·rust
qq_406981032 小时前
c++的decltype是什么
开发语言·c++
坤坤子吖2 小时前
算法学习——单调队列
开发语言·c++·笔记·学习·算法
我就是全世界2 小时前
OpenCode Go 套餐划算吗:先看你用哪个模型
开发语言·后端·golang