Scala中的协变点、逆变点、不变点如何确定?

ABAP CDS 和 HANA SQL 的关系 摘要: ABAP CDS与HANA SQL既有紧密联系又有本质区别。ABAP CDS作为语义数据建模框架,在SQL基础上扩展了业务语义层,通过注解(annotations)、关联关系(associations)等机制为数据附加业务含义,并支持权限控制、客户端处理等ABAP平台特性。虽然CDS实体最终会转换为HANA数据库对象执行,但它并非简单的SQL封装,而是构建了独立于数据库的语义模型。二者在数据库执行层深度融合,ABAP CDS通过代码下推技术将计算任务优化到HANA层完成。实际开发中应优先使用ABAP 阅读详情

阅读《scala编程》时,我们知道了类的类型参数是可以型变(variance)的。型变包含以下三种:

  • 协变(convariant):如果S是T的子类型,则C1[S]也是C1[T]的子类型,则称C1在类型参数T上是协变的。通过定义时再T前面加上+实现。class C1[+T]。P393
  • 不变(nonvariant):不同类型的队列之间永远不存在子类型关系。泛型默认是不变的。 P394
  • 逆变(contravariance):如果S是T的子类型,则C1[T]是C1[S]的子类型。通过定义时再T前面加上-实现。class C1[-T]。

类或特质定义中能出现类型参数的所有位置都会被归类成不同的“点”,这些点可分为

  • 协变点(positive)
  • 逆变点(negetive)
  • 不变点(neutral)。

类型参数在使用上遵守以下规则:

  • 用+注解的类型参数只能用在协变点。
  • 用-注解的类型参数只能用在逆变点。
  • 不用注解的类型参数,可以用再任意点。(也是唯一能用在不变点的类型参数)

令人困扰的是,如何确定,各个位置是什么类型的点呢?书中如下结论到底是怎么来的?

abstract class Cat[-T, +U] {
    def meow[W](volume: T, listener: Cat[U, T]): Cat[Cat[U, T], U]
}
// 书中给的各类型参数的结论如下:+表示协变点,-表示逆变点
abstract class Cat[-T, +U] {
    def meow[W-](volume: T-, listener: Cat[U+, T-]-): Cat[Cat[U+, T-]-, U+]+
}

确定点的类型有如下基本规则和例外情况,按照基本规则和例外情况就可以分析出所有点的类型了。

基本规则:

  1. 从类(或特质)的定义处开始,所有类型参数按照类的嵌套定义生成一颗树。如下图所示。
  2. 树顶部是协变点(positive)
  3. 更深嵌套的层次的点默认跟它上一层的类型相同

在这里插入图片描述
如果有更多其他成员在meow一层定义(如def、 val、 var、 type等),则meow一层还有更多分支。

例外情况:

  1. 方法入参的类型参数的位置被归纳为“翻转”类,具有以下性质:、
    • 逆变点翻转为协变点
    • 协变点翻转为逆变点
    • 不变点翻转后仍为不变点
  2. 方法本身的类型参数的位置也属于“翻转”类。如def f[T]中T的位置。
  3. 类型的类型参数的位置(原文是 type argument position of a type),如a: C[T]中的T,根据C在定义时,T的声明的型变决定,具体的:
    • +T 则类型保持不变
    • -T 则类型变为“翻转”
    • T 则类型变为“不变点”(neutral)

解释书中的样例

abstract class Cat[-T, +U] {
    def meow[W](volume: T, listener: Cat[U, T]): Cat[Cat[U, T], U]
}
// 书中给的各类型参数的结论如下:+表示协变点,-表示逆变点
abstract class Cat[-T, +U] {
    def meow[W-](volume: T-, listener: Cat[U+, T-]-): Cat[Cat[U+, T-]-, U+]+
}

具体解释,以下A-J表示位置:

// 顶点是+的,所以根据基本规则3,则应该有底层的A B C D四个位置都是+的
abstract class Cat[-T, +U] {
    def meow[A](volume: B, listener: C): D
}
// 根据例外情况2,则A翻转,由+变成-的
abstract class Cat[-T, +U] {
    def meow[A-](volume: B, listener: C): D
}

// 根据例外情况1,B,C都翻转成-的,D没有例外,仍是+
abstract class Cat[-T, +U] {
    def meow[A-](volume: B-, listener: C-): D+
}
//C位置继续往下嵌套为Cat[U, T],所以Cat[E, F]的E,F两个位置根据基本规则3,继承C处类型-,
// 然后根据例外情况3,E处定义时为-T,需翻转为+;F处定义时为+U,保持不变为-,则C位置最终为Cat[E+, F-]-
abstract class Cat[-T, +U] {
    def meow[A-](volume: B-, listener: Cat[E+, F-]-): D+
}
// D位置也类似C位置的经过两步分析,第1步得到 Cat[G-, H+]+,第2步得到Cat[Cat[I+, J-]-, H+]+所以最终为:
abstract class Cat[-T, +U] {
     def meow[A-](volume: B-, listener: Cat[E+, F-]-): Cat[Cat[I+, J-]-, H+]+
}

把位置处带入类型参数,即为书本上的结果:
abstract class Cat[-T, +U] {
    def meow[W-](volume: T-, listener: Cat[U+, T-]-): Cat[Cat[U+, T-]-, U+]+
}

参考

国科大作业考试资料-人工智能原理与算法-2024新编-第十一次作业整理 1、有一位教授想知道学生是否睡眠充足。每天,教授观察学生在课堂 上是否睡觉,并观察他们是否有红眼。教授获得如下的领域知识: (1)没有观察数据时,学生睡眠充足的先验概率为0.7。 (2)给定学生前一天睡眠充足为条件,学生在晚上睡眠充足的概率是0.8;如果前一天睡眠不充足,则是0.3。 (3)如果学生睡眠充足,则红眼的概率是0.2,否则是0.7。 (4)如果学生睡眠充足,则在课堂上睡觉的概率是0.1,否则是0.3。 将这些信息形式化为一个动态贝叶斯网络,使教授可以使用这个网络从观察序列中进行滤波和预 阅读详情

相关推荐

mcgs数据查表功能,用于大量数据对比查找对应数据,减少PLC代码

mcgs脚本实现数据查表功能

qq_24866535的博客 3270

Scala 方法与函数

Scala 方法与函数 方法的定义 object Scala_Function { def main(args: Array[String]): Unit = { def max(lhs: Int, rhs: Int): Int = { if (lhs >= rhs) { // return lhs lhs } else {...

Gerald的博客 318

利用HipSTR从二代测序数据中精准解析短串联重复序列(STR)的遗传多态性

本文详细介绍了如何利用HipSTR工具从二代测序(NGS)数据中精准解析短串联重复序列(STR)的遗传多态性。通过三步走策略,HipSTR能够高效识别STR区域、估算重复次数并判定基因型,适用于法医鉴定、疾病研究和细胞系鉴定等多个领域。文章还提供了实战操作指南和常见问题解决方案,帮助研究者充分利用NGS数据开展STR分析。

weixin_28702105的博客 483

“变点和不变点”说明面向对象的设计方法,弱偶合,(interfance,factory等等)

    一:面向对象的 基本原则:我感觉说的就是说类的设计:(1):强内聚(2):弱偶合(3):信息隐藏 。这个包括的方面很广,不仅仅是说类的成员属性的private或是protected;还包括mvc的分层,是各层互相弱偶合,而达到隐藏不需要被看到的程序;还包括使用“不变点”作为“变点”类的访问介质。二:面向对象的 设计方法:(1)纯虚构。是说,为了实现我们的程序功能并使其符

stone_star的专栏 1156

CHARLS数据库下载避坑指南:从注册到数据获取的完整流程(2023最新版)

本文提供2023年最新版CHARLS数据库下载与使用全流程指南,涵盖从注册、数据申请到清洗的高效实践。重点解析邮箱选择、协议签署等关键步骤,并分享多线程下载、格式转换等实用技巧,助力研究者快速获取并处理这一中国中老年健康研究的黄金标准数据。

red88的博客 923

概率论与数理统计基础概念与重要定义汇总

文章目录一、随机事件和概率1:互斥,对立,独立事件的定义和性质。2:概率,条件概率和五大概率公式3:古典型,几何型概率和伯努利试验 一、随机事件和概率 1:互斥,对立,独立事件的定义和性质。 互斥事件\color{red}\textbf{互斥事件}互斥事件 事件A和B的交集为空,A与B就是互斥事件,也叫互不相容事件。也可叙述为:不可能同时发生的事件。如A∩B为不可能事件(A∩B=Φ),那么称事件A与事件B互斥,其含义是:事件A与事件B在任何一次试验中不会同时发生。 则P(A+B)=P(A)+P(B)(这个公

csyifanZhang的博客 1万+

自动售货机Verilog状态机设计:从需求分析到FPGA验证完整实践

在数字IC设计与FPGA开发中,状态机设计是最核心的基本功,而自动售货机控制器则是训练这一能力的经典工程案例。本文从控制通路与数据通路分离的视角,系统梳理状态机设计的基本原理,包括Moore与Mealy型选型、独热码与二进制编码策略、三段式RTL实现方法,以及时序控制与仿真验证的完整流程。通过一个支持多种硬币投币、自动累计金额、超款找零的售货机控制器,深入分析同步逻辑、边沿检测、亚稳态消除和复位设计等关键工程问题。该案例不仅能帮助验证工程师掌握testbench设计与边界条件覆盖技巧,也为后续学习AXI协议

weixin_34315485的博客 742

Ferry工单平台部署

ferry工单平台部署

运维求生之路 1897

scala雾中风景(10): 逆变点与协变点

遇见一个这样的问题 class In[+A]{ def fun(x:A){} } 会提示 error: covariant type A occurs in contravariant position in type A of value x class In[+A]{def fun(x:A){}} ^ 而这样不会出现问题 class In

houzhizhen的专栏 762

基于C++和Qt开发IEC104规约主站调试软件(第二章)

本章节主要讲解iec104主站软件界面设计和从站的连接功能以及部分功能代码的展示。

半青年的博客 860

2篇5章1节:实验流行病学的核心特征和设计原则

本文系统阐释实验流行病学的核心定义、四大核心特征、四大基本原则及主流设计类型,结合骨科、肿瘤科、儿科、精神科、内外妇儿及公共卫生等多学科临床实践案例,具象化解读人为干预、随机分组、平行对照、前瞻性设计的核心内涵与应用价值。同时,规范梳理对照、随机、盲法、重复四大研究基本原则,详细介绍临床试验、现场试验、社区试验三类主流研究设计的适配场景与应用差异。

MD Code 174

【scala类型系统】协变与逆变

scala的协变与逆变

檐前潜心学种瓜 681

SAP Fiori Launchpad 上看不到任何 tile 应该怎么办?

中心UI组件是一个框架,为所有SAPFiori应用程序提供公共基础设施SAPFiorilaunchpad是所有SAPFioriUI的基础,并为SAPFiori应用程序提供基本功能,如登录,界面大小,应用程序之间的导航,和基于角色的应用程序目录。ABAP前端服务器包含所有基础设施组件,用于为客户端生成SAPFiori应用程序特定的UI,并与SAPBusinessSuite后端系统通信。SAPFiori应用程序的处理过程如下首先,客户端加载SAPFiori应用程序的界面。...

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 941

Scala型变深度解析:协变与逆变在泛型编程中的核心作用

型变描述了泛型类型的子类型关系如何随着类型参数的变化而变化。协变用+T表示,意味着如果A是B的子类型,那么也是的子类型。子类型关系朝着与类型参数相同的方向变化。// 定义一个协变容器// 注意:不能定义 set(value: T) 方法,原因后面会解释// 类型层次// 协变的威力val animalBox: CovariantBox[Animal] = dogBox // 合法!协变允许// 现在可以统一处理逆变用-T表示,意味着如果A是B的子类型,那么是的子类型。

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 2273

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Scala教程之:深入理解协变和逆变

文章目录函数的参数和返回值可变类型的变异 在之前的文章中我们简单的介绍过scala中的协变和逆变,我们使用+ 来表示协变类型;使用-表示逆变类型;非转化类型不需要添加标记。 假如我们定义一个class C[+A] {} ,这里A的类型参数是协变的,这就意味着在方法需要参数是C[AnyRef]的时候,我们可以是用C[String]来代替。 同样的道理如果我们定义一个class C[-A] {}, 这...

程序那些事 3480

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Scala之 协变、逆变和不变

基本介绍 Scala的协变(+),逆变(-),协变covariant、逆变contravariant、不可变invariant 对于一个带类型参数的类型,比如 List[T],如果对 A 及其子类型 B,满足 List[B]也符合 List[A] 的子类型,那么就称为 covariance(协变) ,如果 List[A]是 List[B]的子类型,即与原来的父子关系正相 反,则称为 contra...

李昊轩的博客 808

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

型变(协变、逆变、不变)、泛型类

型变 一、协变 class Covariant[+T]{ } 对于两种类型 A 和 B,如果 A 是 B 的子类型,那么 Covariant[A] 就是 Covariant[B] 的子类型 二、逆变 class Inversion[-T]{ } 对于两种类型 A 和 B,如果 A 是 B 的子类型,那么 Inversion[B] 就是 Inversionr[A] 的子类型 三、不变 class Invariant[T]{ } 默认情况下,Scala中的泛型类是不变的 如下图所示: 案例: package

qianchun22的博客 1113

Scala 入门-型变,协变,逆变,不变

专栏原创出处:github-源笔记文件 ,github-源码 ,欢迎 Star,转载请附上原文出处链接和本声明。 Scala 编程语言专栏系列笔记,系统性学习可访问个人复盘笔记-技术博客 Scala 编程语言 什么是型变 型变就是复杂类型的数据其组件类型存在继承关系时,复杂类型数据是否也有相对应的关系。 泛型类的类型参数支持型变注释,允许它们是协变的,逆变的,在没有使用注释的情况下是不...

2.wa 598

scala协变逆变上界下界---理解篇

如果你对面向对象的泛型bt

OopsOutOfMemory盛利的博客 9984

Scala协变和逆变【关键在于找到谁是爸爸】

一、协变与逆变的介绍 正常来说创建一个Person类,然后可以创建一个Student类继承Person来继承他。当我们创建对象的时候可以用父类类型指向子类实例。 再java中父类类型指向子类实例是可以的,当然再scala中也是可以存在的。但是如果是list[Person]那就不是list[Student]的父类了。再java中不存在协变与裂变,也就没有办法让list[Person]成为list[Student]的父类。 再scala中不仅可以让list[Person]成为list[Student]的父类,甚

lyq7269的博客 1057

Scala入门到精通——第二十一节 类型参数(三)-协变与逆变

本节主要内容 协变 逆变 类型通匹符 1. 协变 协变定义形式如:trait List[+T] {} 。当类型S是类型A的子类型时,则List[S]也可以认为是List[A}的子类型,即List[S]可以泛化为List[A]。也就是被参数化类型的泛化方向与参数类型的方向是一致的,所以称为协变(covariance)。 为方便大家理解,我们先分析java语言中为什么不存在协变及下一

摇摆少年梦的技术博客 1万+

Scala系列22:Scala泛型,非变,协变,逆变等使用详解

0.泛型 scala和Java一样,类和特质、方法都可以支持泛型。我们在学习集合的时候,一般都会涉及到泛型。所以泛型,简单点理解就是定义(类,方法等)不指定具体数据类型,而在使用时才传入具体使用类型,这样的好处就是支持多类型的复用。 0.1定义一个泛型方法 在scala中,使用方括号[]来定义类型参数。 语法格式 def 方法名[泛型名称](..) = { //... } 示例说明 用一个方法来获取任意类型数组的中间的元素 不考虑泛型直接实现(基于Array[Int]实现) 加

涤生大数据 2306

scala 协变和逆变 在函数上的应用

协变的 covariant;逆变的 contravariant C是AnyRef类。函数的协变和逆变

iamiman的博客 1689

scala 协变和逆变_Scala方差:协变,不变和逆变

scala 协变和逆变In this post, we are going to discuss about Scala Variance and it’s use cases. 在本文中,我们将讨论Scala Variance及其用例。 什么是方差? (What is Variance?) Variance defines Inheritance relationships of Param...

从零开始的教程世界 414

协变(Covariance)、逆变(Contravariance)与不变(Invariance)in Scala

协变如果 A 是 B 的子类型,那么 List[A] 就是 List[B] 的子类型使用注释+A,可以使一个泛型类的类型参数 A 成为协变。对于某些类 class List[+A],使 A 成为协变意味着对于两种类型 A 和 B,如果 A 是 B 的子类型,那么 List[A] 就是 List[B] 的子类型。这允许我们使用泛型来创建非常有用和直观的子类型关系Scala 标准库有一个通用的不可变的类 sealed abstract class List[+A],其中类型参数 A 是协变的。......

m0_52313753的博客 822

Java与Scala的协变与逆变

Java与Scala的协变与逆变

Forrestleo的博客 606
上一篇: 【Python】Python基础快速入门
下一篇: log4j配置文件读取的几种方式
Code_LT
博客等级 码龄10年 307粉丝 182原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值