Scala 逆变和协变

2023-12-13

我正在研究 scala 的类型系统,发现了一个奇怪的情况。我有充分的理由相信,我不懂协变和协变。

这是我的问题案例:

我有两个类,Point 和 ColorPoint,它是 Point 的子类。

class Point(val x : Int, val y : Int)
class ColorPoint(x : Int, y : Int, val red : Int, val green : Int, val blue : Int) extends Point(x,y) 

该类将 B 转换为 A,而 B 应该是 A 的超类型:

class CoVariance[+A]{
 def cast[B >: A](x : B) : A = {
  return x.asInstanceOf[A] 
 }
}

该类将 B 转换为 A,而 B 应该是 A 的超类型:

class ContraVariance[-A]{
 def cast[B, A <: B](x : B) : A = {
    return x.asInstanceOf[A]
 }
}

Case 1:

val co = new CoVariance[Point]
val color_point = new ColorPoint(1,2,3,4,5)
val point_co = co.cast(color_point) 
println(point_co.x)

如果我写出来:

// Covariance[Point] -> 
// cast[B :> Point](x : B) : Point -> (fill in ColorPoint)
// Cast[ColorPoint :> Point] : Point 

我认为这是不正确的,因为 ColorPoint 不是 Point 的超类型,但 scala 不会抱怨。

下一个:

val contra = new ContraVariance[Point]
val color_point_contra = new ColorPoint(1,2,3,4,5)
val point_contra = contra.cast(color_point_contra) 
println(point_contra.x)

如果我写出来:

// ContraVariance[Point] -> 
// cast[B, Point <: B](x : B) : Point -> (fill in ColorPoint)
// cast[ColorPoint, Point <: ColorPoint] : Point 

我也希望这是不正确的,但 scala 不会抱怨。我想说 Point 不是 ColorPoint 的子类型。

我的推理正确还是我遗漏了什么?


我认为您误解了协变和逆变位置是什么。这并不意味着您能够cast某些类型之间,它只是建立参数化类型之间的继承关系。

您只能将类型参数标记为协变或逆变位置。当你说Container[+A],你是说你可以处理所有的实例Container[A]作为子类型Container[B] if A是一个子类型B。这对于不可变容器类是有意义的:您可以想到一个List[Person]成为...的父母List[Employee]。请注意,这并没有提及转换规则——这些规则保持不变。

逆变类似,但相反。如果你有Writer[-A], 它说Writer[A]是一个子类型Writer[B] if B是一个子类型A。您也可以看到这也具有直观意义:如果您有一个Writer[Person]作为可以将一个人写入某个目的地的东西,你有Writer[Employee]作为一个只能写员工的作家,这是有道理的Writer[Employee]成为...的父母Writer[Person]自从写了一个Person是编写完整的子任务Employee,尽管类型本身是相反的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scala 逆变和协变 的相关文章

随机推荐

  • 如何仅对字符串的一小部分执行字符串替换?

    我想要一种有效的方法 可以起到这样的作用 编辑 抱歉 我没有输入我之前尝试过的内容 我现在更新了这个例子 Method signature Only replaces first instance or how many are speci
  • webpack 捆绑的 React 应用程序中的 node-mssql 错误

    每当我尝试使用时 我的 React 应用程序都无法构建节点 MSSQL图书馆 在客户端执行此操作很重要 因为我必须从旧的 IIS 服务器提供此应用程序 看来在 Webpack 浏览器包中执行需要额外的配置 也许是某种 Polyfill 我在
  • 对 PHP 输出的 HTML 属性进行双引号转义

    通常 在编写 PHP 时 我会让它输出一些像这样的 HTML echo a href title link title link text a 显然这不会解析 因为我需要转义属性中的双引号 a 元素 是否有一个正则表达式可以快速执行此操作
  • 消息:无法使用 Selenium Manager 获取 chromedriver

    我尝试在我的 jupyter 笔记本上编写此代码 它显示了错误 我的目标是进行网络抓取 driver webdriver Chrome ChromeDriverManager install 在此输入图像描述 我还使用 pip 安装了 se
  • LAN 中的主机未解析

    我在 HttpPost 上收到 IOExeption 主机未解析 在本例中 端点是我的 LAN 上具有 Web 服务的计算机 http pc259 8080 test service asmx 我的 LAN 使用 WIFI Android
  • 如何在同一图中绘制由 statsmodels 绘图函数创建的图

    我有以下代码 from statsmodels graphics factorplots import interaction plot import statsmodels api as sm import matplotlib pypl
  • 使用归一化互相关匹配对象外部形状

    我正在与normxcorr2Matlab中的模板匹配函数 然而我想做的和我想做的不一样normxcorr2做 内置的normxcorr2考虑矩形模板中的所有像素来计算互相关 但我只希望某些像素参与归一化互相关过程 例如 我只想在关联时将下图
  • MATLAB:在 RGB 图像上应用透明蒙版并与另一个图像混合

    我有 2 张图像 前景和背景 前景是一个范围从 50到300的数字矩阵 我通过imagesc显示它 即这不是 RGB 图像 背景是 RGB 图像 我想首先在前景上应用透明蒙版来改变它的外观 这很容易通过使用 altered foregrou
  • Android:如何防止软键盘将我的视图向上推?

    我的应用程序底部有一个垂直滑动抽屉 当软键盘打开时 它会将抽屉的标签向上推 使其位于键盘顶部 我实际上希望它保留在屏幕底部 在显示键盘时隐藏 还有其他人遇到这个问题吗 知道如何解决吗 您只需切换您的 ActivitywindowSoftIn
  • WP7背景音频资源不再可用

    我在用着BackgroundAudioPlayer用于我的 Windows Phone 7 音乐和视频应用程序 播放一些音乐后 我使用MediaPlayerLauncher 然后按 返回 返回到我的应用程序 每当我使用时Background
  • 如何选择模板标签内的元素? [复制]

    这个问题在这里已经有答案了
  • 根据另一个查找/映射数组替换数组中的键

    我有一个以下形式的关联数组key gt value其中 key 是一个数值 但它不是连续的数值 键实际上是一个 ID 号 值是一个计数 这对于大多数情况来说都很好 但是我想要一个函数来获取人类可读的数组名称并将其用作键 而不更改值 我没有看
  • 如何在 Matplotlib 中绘制没有线和点的误差条图?

    我目前正在使用以下代码来绘制误差条图 plt errorbar log I mean log V2 mean xerr yerr 然而 最终结果显示每个误差条交点的中心有一个圆形点 如何按照科学工作的要求只绘制误差线而不绘制中心点 use
  • 空 XmlHttp 响应文本(仅限 Google Chrome)

    我的 Google Chrome 聊天脚本有问题 有时 响应文本是空的 直到您重新加载页面 但有时它运行良好 它每秒打开一个 xmlhttp 连接 如果第一个连接好 那么后面的连接也好 在 Firefox 中 它总是好的 var url t
  • 了解 Javascript 回调参数

    关于回调的一些问题 使用一些示例代码 function uploadPhoto params var win function response console log Success console log Response respon
  • 有没有办法从控制器获取计划任务作为数组? [复制]

    这个问题在这里已经有答案了 我想从控制器获取计划任务列表 一些套餐 articles乃至堆栈溢出解释如何从命令显示它 但我没有找到如何在没有命令的情况下执行此操作 我的目标是获取一系列计划任务及其日期和描述 有没有办法从控制器获取计划任务作
  • 如何替换字符串中的括号

    我有一个包含标记的字符串列表 令牌是 ARG 令牌名称 我还有令牌的哈希图 其中键是令牌 值是我想要替换令牌的值 当我使用 replaceAll 方法时出现错误 java util regex PatternSyntaxException
  • mysql_real_escape_string() 无法建立到服务器的链接

    当我尝试使用 mysql real escape string 时出现此错误 Access denied for user ODBC localhost using password NO 我不明白为什么我必须连接到数据库来检查这些值是否可
  • 将 JSF 与 Spring 集成

    我还没有实现任何代码 我仍在研究新应用程序的整体架构 这将是我第一次使用JSF Spring 我需要将 Web 服务放在 Spring 服务 bean 业务逻辑层 前面 因为这些 bean 可以被表示层之外的其他应用程序访问 在为应用程序定
  • Scala 逆变和协变

    我正在研究 scala 的类型系统 发现了一个奇怪的情况 我有充分的理由相信 我不懂协变和协变 这是我的问题案例 我有两个类 Point 和 ColorPoint 它是 Point 的子类 class Point val x Int val