Scala之泛型详解

泛型用于指定类或方法可以接受任意类型参数,参数在实际使用时才被确定,泛型可以有效地增强程序的适用性,使用泛型可以使得类或方法具有更强的通用性。泛型的典型应用场景是集合及集合中的方法参数,可以说同 Java 一样,Scala 中泛型无处不在,具体可查看 Scala 的 API

泛型基础

泛型,即“参数化类型”,就是将类型由原来的具体类型参数化,然后在使用/调用时传入具体的类型。泛型的本质是为了参数化类型,在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、特质和方法中,分别被称为泛型类泛型方法泛型特质

泛型类:指定类可以接受任意类型参数。在创建对象时, 可以指定具体的类型,传参值要与指定类型一致,或者不指定类型,基于传参值自动推断类型。

// 定义泛型类 Student ,泛型 T 和 N
class Student[T,N](name:T,var age:N) {
      def show():Unit = {
          println(s"name:$name, age:$age")
      }
}
// 传参值要写入泛型指定的类型
val a = new Student[String,Int]("张三",33)
a.show()
// 不指定类型,自动推断类型 
val b = new Student("李四","六十")
b.show() 

在这里插入图片描述

泛型方法:指定方法可以接受任意类型参数。在调用方法时, 可以明确具体的数据类型,或者不指定类型,基于传参值自动推断类型。

// 定义泛型方法show
def show[T](x:T):T = { x }
// 指定了方法类型
val a = show[String]("hi")
// 自动推断类型
val b = show(33)
val c = show(9.9)

在这里插入图片描述

泛型特质:指的是把泛型定义到特质的声明上, 即:该特质中的成员的参数类型是由泛型来决定的. 在定义泛型特质的子类或者子单例对象时, 明确具体的数据类型。

// 泛型特质 Person
trait Person[T]{
      def show():T
}

// 泛型类 Student , 继承指定为String类型的特质
class Student[N](name:String,age:N) extends Person[String]{
      override def show():String = {
          "name:"+name+", age:"+age
      }
}
// 参数要写入泛型定义的指定的类型,不指定泛型,会基于传递的参数值自动推断类型
val a = new Student[Int]("张三",33)
a.show() 
val b = new Student("李四","六十")
b.show() 

在这里插入图片描述

泛型标记符:
E - Element (在集合中使用,因为集合中存放的是元素)
T - Type(一般类型)
K - Key(键)
V - Value(值)
N - Number(数值类型)
_ - 表示不确定的类型

类型变量界定

类型变量界定是指在泛型的基础上,对泛型的范围进行进一步的界定,从而缩小泛型的具体范围,即限定该泛型必须从哪个类继承、或者必须是哪个类的父类。这就是泛型的上界与下界。
上界 :使用 [T <: 类型] 表示给类型添加一个上界,表示泛型参数必须是从该类型本身或该类型的子类型。
下界 :使用 [T >: 类型] 表示给类型添加一个下界,表示泛型参数必须是从该类型本身或该类型的父类型。
示例:

// T 必须继承自实现了Comparable的类, 才能执行compareTo方法,否则报错
def compare[T <: Comparable[T]](x:T, y:T) = { 
    if(x.compareTo(y) > 0) x else y 
} 
compare("A", "B")

在这里插入图片描述

视图界定

上面讲的类型变量界定建立在类继承层次结构的基础上,但有时候这种限定不能满足实际要求,如果希望跨越类继承层次结构时,可以使用视图界定来实现,其原理是通过隐式转换来实现。

隐含参数和方法也可以定义隐式转换,称作视图。视图的绑定从另一个角度看就是 implicit 的转换。主要用在两个场合:① 当一个 T 类型的变量 t 要装换成 A 类型时。 ② 当一个类型 T 的变量 t 无法拥有 A 类型的 a 方法或变量时。其实视图的绑定是为了更方便的使用隐式装换,视图界定利用 <% 符号来实现。
示例代码

// 除可以接受 String 及其子类外,也可以接受可以隐式转换为 String 类型的类型
def concat[T <% String](x:T, y:T):String = { x + y } 
// 定义一个 Int 转换 String 的隐式函数
implicit def intToString(i:Int) = i.toString
// Int类型会隐式转换为String类型,然后做字符串拼接
concat(165,173)

在这里插入图片描述

协变、逆变与不变

协变(+)

C[+T]:当类型 B 是类型 A 的子类型时,则 C[B] 也可以认为是 C[A] 的子类型,即 C[B] 可以泛化为 C[A]。也就是被参数化类型的泛化方向与参数类型的方向是一致的,所以称为协变 (covariance) 。比如 List[+T]

class Person  //父类
class Student extends Person //子类
class Covariance[+T]  //协变
val a:Covariance[Person] = new Covariance[Student] // Covariance[Person] 是 Covariance[Student] 的父类

在这里插入图片描述

逆变(-)

C[-T]:当类型 B 是类型 A 的子类型,则 C[A] 反过来可以认为是 C[B] 的子类型。也就是被参数化类型的泛化方向与参数类型的方向是相反的,所以称为逆变(contravariance) 。比如Queue[-T]

class Person  //父类
class Student extends Person //子类
class Contravariance[-T]  //逆变
val b:Contravariance[Student] = new Contravariance[Person] // Contravariance[Person] 是 Contravariance[Student] 的子类

在这里插入图片描述

不变

C[T]:无论类型 B 与类型 A 是什么关系, C[A]C[B] 没有从属关系,称为不变(invariance) 。

class Person  //父类
class Student extends Person //子类
class Invariance[T]  //不变
val a:Invariance[Person] = new Invariance[Student] // Invariance[Person] 与 Invariance[Student] 没有从属关系
val b:Invariance[Student] = new Invariance[Person] // Invariance[Person] 与 Invariance[Student] 没有从属关系

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/33832.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LabVIEW开发基于直流电机的高精度定位火星车

LabVIEW开发基于直流电机的高精度定位火星车 火星探测器一直用于火星探测的自动无人驾驶车辆。这些机器人远程车辆用于避免对人类不公平的条件&#xff0c;并减少与之相关的危险。这一研究领域引起了许多科学家和研究人员的注意&#xff0c;这导致了这一技术领域的显着进步。已…

Quartz任务调度笔记

一、概念 1.1简介 Quzrtz是OpenSymphony开源组织在Job scheduling领域的开源项目 特点&#xff1a;Quartz具有丰富特性的"任务调度库"&#xff0c;能够集成于任何的Java应用&#xff0c;小到独立的应用&#xff0c;大到电子商业系统。quartz能够创建亦简单亦复杂的调…

如何建立一个企业网站

建立一个企业网站的方法 1、好。如果你的网站将专注于你已经有了一个不错的主意&#xff0c;请跳过此步骤。如果不是&#xff0c;这里有一些事情来帮助你找出答案。首先&#xff0c;要明白&#xff0c;有几十亿人在互联网上&#xff0c;一个健康的比例有自己的网站。如果你限制…

ResizeKit.NET 自动更改所有控件和字体大小 -Crack Version

ResizeKit2.NET ---Added support for Microsoft .NET 7.0. 使您的应用程序大小和分辨率独立。 ResizeKit.NET 自动更改所有控件和字体的大小&#xff0c;以便它们可以显示在任何大小的表单上。提供完全控制来自定义调整大小过程。即使用户在运行应用程序时切换表单的大小&…

探索 Spring Boot 项目全过程

文章目录 &#x1f387;前言1.Spring Boot 所需环境2.Spring Boot 项目创建2.1 安装插件2.2 创建新项目2.3 项目属性配置2.4添加依赖2.4 修改项目名称2.5 添加框架支持2.6 目录介绍 3.判断Spring Boot 创建项目是否成功&#x1f386;总结 &#x1f387;前言 在 Java 这个圈子&…

Qt在Ubuntu下如何进行桌面软件开发?

文章目录 0.引言1.新建项目2.编写第一个程序3.在Qt外部启动程序 0.引言 笔者研究的方向涉及在ubuntu中运行代码&#xff0c;早先是直接利用控制台运行代码文件&#xff0c;在控制台中虽然设法将代码精简到一个三个文件中&#xff0c;只需要在控制台运行这三个文件即可&#xff…

使用itextpdf填充表单域并生成pdf

文章目录 前言一、准备工作1.1 安装软件1.2 准备pdf1.3 设置表单域 二、创建项目三、编写代码3.1 编写工具类3.2 测试 四、测试结果 前言 最近手上有个任务&#xff0c;就是需要做一个pdf导出的功能。 可选择的技术点比较多&#xff0c;我这边综合考虑之后&#xff0c;使用的…

第五课—大学英语四六级备考—听力专项

Key words 1.implement vt.实施 "Implement" 在中文中的意思是「实施」或「执行」。以下是一些示例用法和搭配&#xff1a; 中文意思&#xff1a;实施、执行 形近字&#xff1a;implicate&#xff08;牵连&#xff09; 1. 用英文造句&#xff1a;The government …

微信小程序浏览docx,pdf等文件在线预览使用wx.openDocument

wx.downloadFile({ url: fileUrl,//pdf链接success(res) {wx.openDocument({ //打开文档filePath: res.tempFilePath,fileType: "pdf",//文档类型showMenu: true,success: function (res) {wx.showToast({title: 打开文档成功,})},fail: function (res) {wx.showToas…

vue封装svg组件来修改svg图片颜色

文章目录 1、引入依赖2、根目录的vue.config.js配置3、在组件文件夹(compontents)中创建svgIcon.vue4、在src目录下创建icons文件5、处理svg格式的图片6、在main.js文件中引入icons文件中的index.js文件7、使用8、效果图1、项目成功运行后的样子2、直接在html上添加样式&#x…

LangChain:LLM应用程序开发(中)——文档问答、评估、Agents(代理)

文章目录 四、文档问答4.1 快速入门4.2 逐步实现4.3 其它方法 五、评估5.1 创建QA app5.2 生成测试数据点5.2.1 Hard-coded examples5.2.2 LLM-Generated examples 5.3 link chain debug手动评估5.4 LLM assisted evaluation5.5 LangChain Evaluation platform 六、Agents&…

论文笔记 CPU Accounting for Multicore Processors

Abstract 确定了对CPU utilization的不准确测量是如何影响OS的几个关键方面的这篇文章提出来了一个比CPU utilization更准确的性能评估指标 In this paper, we identify how an inaccurate measurement of the CPU utilization affects several key aspects of the system suc…

Python 基本数据类型(三)

文章目录 每日一句正能量数值运算数值类型实例String&#xff08;字符串&#xff09; 每日一句正能量 人的相处&#xff0c;靠的是真心&#xff0c;不是套路。合得来的人&#xff0c;坦诚相待&#xff0c;合不来的人&#xff0c;客气寒暄&#xff1b;谁也别给谁冷脸看&#xff…

期末复习【计算机网络】

期末复习【计算机网络】 前言推荐期末复习如何快速阅读电子书重点第1章 概述1.6 计算机网络的性能1.6.2 计算机网络的性能指标√ 1.7 计算机网络体系结构1.7.3 具有五层协议的体系结构√ 第2章 物理层2.3 物理层下面的传输媒体 *2.4 信道复用技术2.4.1 频分复用、时分复用和统计…

LeetCode 剑指 Offer 13. 机器人的运动范围(深度遍历)

LeetCode 剑指 Offer 13. 机器人的运动范围 原题思路代码运行截图收获 原题 LeetCode 剑指 Offer 13. 机器人的运动范围 思路 通过深度遍历来找出所有可达的格子通过0、1、2来区分未遍历、可到达、不可到达三种状态 代码 class Solution { public:int visited[109][109];i…

【计算机网络】数据链路层--点对点协议PPP

1.概念 2.构成 3.封装成帧 - 帧格式 4.透明传输 4.1字节填充法&#xff08;面向字节的异步链路&#xff09; 4.2.比特填充法&#xff08;面向比特的同步链路&#xff09; 5.差错检测 6.工作状态 7.小结

Webpack和Vite简单使用

目录 WebPack 介绍 基础使用 初始化使用 webpack.config.js文件 webpack开发服务器 vite 介绍 使用 使用vite创建vue框架项目 WebPack 介绍 当我们习惯了在node中编写代码的方式后&#xff0c;在回到前端编写html、css、js这些东西会感觉到各种的不便。比如: 不能放心…

【Linux】硬链接 和 软链接

为了方便用户访问文件&#xff0c;Linux提供了一种称为连接&#xff08;link&#xff09;的机制&#xff0c;可以将一个文件或目录与另一个文件或目录建立关联&#xff0c;从而实现多个路径指向同一个文件或目录的效果。 一、概述二、硬链接和软链接详解2.1 硬链接2.11 硬链接的…

C++ 模板

模板是泛型编程的基础&#xff0c;泛型编程即以一种独立于任何特定类型的方式编写代码。 模板是创建泛型类或函数的蓝图或公式。库容器&#xff0c;比如迭代器和算法&#xff0c;都是泛型编程的例子&#xff0c;它们都使用了模板的概念。 每个容器都有一个单一的定义&#xf…