Kotlin协变与逆变区别

在Kotlin中,协变和逆变是泛型编程中的两个重要概念,它们允许我们在类型系统中更加灵活地处理类型关系。
1.协变:协变允许我们使用比原始类型更具体的类型。在kotlin中,通过在类型参数上加out关键字来表示协变,生产者,例如,如果我们有一个泛型类List,其中T是一个协变类型参数,那么我们可以将List赋值给List,因为String是Any的子类型。

2.逆变:逆变允许我们使用比原始类型更一般的类型。在kotlin中,通过在类型参数上加in关键字来表示逆变,消费者,例如,如果我们有一个泛型函数fun foo(list: List),其中T是一个逆变类型参数,那么我们可以将List传递给foo函数,因为Any是String的超类型。

协变代码举例:

interface Producer<out T> {//协变 out 类似java中的 extendfun produce(): T
}
open class Fruit
open class Apple: Fruit()class FruitProducer:Producer<Fruit> {override fun produce(): Fruit {return Fruit()}
}class AppleProducer:Producer<Apple> {override fun produce(): Apple {return Apple()}
}fun <T> processProduce(producer:Producer<T>) {val product = producer.produce()println(product)
}fun main(){var fruitProducer:Producer<Fruit> = FruitProducer()var appleProducer:Producer<Apple> = AppleProducer()processProduce(fruitProducer)processProduce(appleProducer)
//    appleProducer = fruitProducer  //报错,协变,不允许将Producer<Fruit>赋值给Producer<Apple>
//    fruitProducer = appleProducer //协变,允许将Producer<Apple>赋值给Producer<Fruit>}

逆变代码举例:

interface Consumer<in T>{ //逆变 in 类似java中的superfun consume()
}class FruitConsumer:Consumer<Fruit>{override fun consume() {println("consume fruit")}
}class AppleConsumer:Consumer<Apple>{override fun consume() {println("consume apple")}
}inline fun <T> processConsumer(consumer:Consumer<T>){consumer.consume()
}fun main() {var fruitConsumer:Consumer<Fruit> = FruitConsumer()var appleConsumer:Consumer<Apple> = AppleConsumer()processConsumer(fruitConsumer)processConsumer(appleConsumer)
//    fruitConsumer = appleConsumer //报错,逆变,不允许将Consumer<Apple>赋值给Consumer<Fruit>
//    appleConsumer = fruitConsumer  //允许将Consumer<Fruit>赋值给Consumer<Apple>,}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何调试Linux内核?

通过创建一个最小的根文件系统&#xff0c;并使用QEMU和GDB进行调试。 1.准备工作环境 确保系统上安装了所有必要的工具和依赖项。 sudo apt-get update //更新一下软件包 sudo apt-get install build-essential git libncurses-dev bison flex libssl-dev qemu-system-x…

Java 调试模式下 Redisson 看门狗失效

一、场景分析 前几天在做分布式锁测试&#xff1a; 在调试模式下&#xff0c;lock.lock() 之后打上断点&#xff0c;想测试一下在当前线程放弃锁之前&#xff0c;别的线程能否获取得到锁。 发现调试模式下&#xff0c;看门狗机制失效了&#xff0c;Redis 上 30 秒后&#xff0…

GPT-4.5震撼登场,AI世界再掀波澜!(3)

GPT-4.5震撼登场&#xff0c;AI世界再掀波澜! GPT-4.5震撼登场&#xff0c;AI世界再掀波澜!(2) &#xff08;一&#xff09;伦理困境&#xff1a;如何抉择 GPT-4.5 的强大功能在为我们带来诸多便利的同时&#xff0c;也引发了一系列深刻的伦理问题&#xff0c;这些问题犹如高…

【数据挖掘】Pandas

Pandas 是 Python 进行 数据挖掘 和 数据分析 的核心库之一&#xff0c;提供了强大的 数据清洗、预处理、转换、分析 和 可视化 功能。它通常与 NumPy、Matplotlib、Seaborn、Scikit-Learn 等库结合使用&#xff0c;帮助构建高效的数据挖掘流程。 &#x1f4cc; 1. 读取数据 P…

七、JOIN 语法详解与实战示例

一、JOIN 的作用与分类 JOIN 操作用于合并两个或多个表的行&#xff0c;基于表之间的关联字段。以下是常见的 JOIN 类型&#xff1a; JOIN 类型描述INNER JOIN返回两个表匹配的记录LEFT JOIN返回左表所有记录 右表匹配记录&#xff08;右表无匹配则为NULL&#xff09;RIGHT …

2019年01月全国POI数据分享(同源历史POI分享系列)

2019年01月全国范围POI数据 2019年01月份全国范围历史POI数据&#xff0c;全国范围所有类别共59336781个POI 2019年01月全国范围POI数据按大类统计 大类代码大类名称2019年01月该类POI数量010000汽车服务1151164020000汽车销售213647030000汽车维修517367040000摩托车服务1800…

Spring Boot + MyBatis 实现 RESTful API 的完整流程

后端开发&#xff1a;Spring Boot 快速开发实战 引言 在现代后端开发中&#xff0c;Spring Boot 因其轻量级、快速开发的特性而备受开发者青睐。本文将带你从零开始&#xff0c;使用 Spring Boot MyBatis 实现一个完整的 RESTful API&#xff0c;并深入探讨如何优雅地处理异…

使用Python开发以太坊智能合约:轻松入门与深度探索

使用Python开发以太坊智能合约&#xff1a;轻松入门与深度探索 随着区块链技术的快速发展&#xff0c;以太坊作为最为成熟和广泛使用的智能合约平台&#xff0c;成为了开发去中心化应用&#xff08;DApp&#xff09;的核心工具。智能合约不仅是区块链技术的基础&#xff0c;更…

ES scroll=1m:表示快照的有效时间为1分钟。怎么理解

在Elasticsearch中&#xff0c;scroll1m 表示你创建的 scroll 上下文 的有效时间为 1分钟。这个参数控制了你可以在多长时间内继续使用这个 scroll_id 来获取更多的数据。 什么是 Scroll 上下文&#xff1f; 当你使用 scroll API 时&#xff0c;Elasticsearch 会为你的查询创…

Linux与UDP应用1:翻译软件

UDP应用1&#xff1a;翻译软件 本篇介绍 本篇基于UDP编程接口基本使用中封装的服务器和客户端进行改写&#xff0c;基本功能如下&#xff1a; 从配置文件dict.txt读取到所有的单词和意思客户端向服务端发送英文服务端向客户端发送英文对应的中文意思 配置文件内容 下面的内…

Jeecg-Boot 开放接口开发实战:在 Jeecg-Boot 的jeecg-system-biz中添加一个controller 实现免鉴权数据接口

Jeecg-Boot 开放接口开发实战&#xff1a;在 Jeecg-Boot 的jeecg-system-biz中添加一个controller 实现免鉴权数据接口 一、场景需求分析 在微服务架构中&#xff0c;常需要快速实现以下两类接口&#xff1a; 开放接口&#xff1a;无需登录即可访问&#xff08;如数据查询、…

C++ ++++++++++

初始C 注释 变量 常量 关键字 标识符命名规则 数据类型 C规定在创建一个变量或者常量时&#xff0c;必须要指定出相应的数据类型&#xff0c;否则无法给变量分配内存 整型 sizeof关键字 浮点型&#xff08;实型&#xff09; 有效位数保留七位&#xff0c;带小数点。 这个是保…

构建安全的Docker基础镜像:从最佳实践到自动化加固

引言 容器化技术的普及使得Docker镜像成为软件交付的核心载体,但镜像中的安全漏洞、敏感信息泄露和权限配置不当等问题可能引发严重风险。本文结合OWASP容器安全指南与一线运维经验,系统化讲解如何构建安全的Docker基础镜像,覆盖镜像构建、依赖管理、运行时防护全链路,并提…

BKA-CNN基于黑翅鸢算法优化卷积神经网络的数据多特征分类预测Matlab

BKA-CNN基于黑翅鸢算法优化卷积神经网络的数据多特征分类预测Matlab 目录 BKA-CNN基于黑翅鸢算法优化卷积神经网络的数据多特征分类预测Matlab分类效果基本介绍BKA-CNN基于黑翅鸢算法优化卷积神经网络的数据多特征分类预测一、引言1.1、研究背景和意义1.2、研究现状1.3、研究目…

SOLID Principle基础入门

(Robert C. Martin (Uncle Bob)) 什么是SOLID原则&#xff1f; SOLID原则是面向对象编程&#xff08;OOP&#xff09;中编写高质量代码的指导方针。实际上&#xff0c;即使不使用SOLID原则&#xff0c;仅通过类、继承、封装和多态性&#xff0c;也可以让程序正常运行。那么为…

轻松实现语音生成:GPT-SoVITS V2整合包的远程访问操作详解

文章目录 前言1.GPT-SoVITS V2下载2.本地运行GPT-SoVITS V23.简单使用演示4.安装内网穿透工具4.1 创建远程连接公网地址 5. 固定远程访问公网地址 前言 今天要给大家安利一个绝对能让你大呼过瘾的声音黑科技——GPT-SoVITS&#xff01;这款由花儿不哭大佬精心打造的语音克隆神…

Python线程池知多少

目录 目标 Python版本 官方文档 概述 线程池 实战 创建线程池的基本语法 批量提交任务 生产者&消费者模型 目标 掌握线程池的基本概念和使用方法。 Python版本 Python 3.9.18 官方文档 concurrent.futures — Launching parallel taskshttps://docs.python.org/3…

(转)SpringBoot和SpringCloud的区别

&#xff08;转&#xff09;SpringBoot和SpringCloud的区别&#xff1a;

中科大 计算机网络组成原理 1.4 接入网和物理媒体 笔记

一、接入网核心功能与架构 ‌核心作用‌ 接入网是连接用户终端与核心网络的桥梁&#xff0c;承担用户身份认证、带宽分配、数据加密等功能&#xff0c;直接影响网络服务的可靠性和用户体验。例如&#xff0c;杭州电视台的数字人主播通过光纤专线实现零失误新闻播报&#xff0c;…

阿里云音频算法岗内推

1、视频云直播、连麦&#xff0c;点播&#xff0c;短视频&#xff0c;媒体生产与处理等服务相关的实时/非实时的音频分析和处理&#xff1b; 2、音频处理算法&#xff0c;包括多场景降噪、自动增益控制、回声消除等&#xff1b; 3、音频特效算法研发&#xff0c;包括变调变速…