0

0

Scala 中的类型推断是双向的,而非隐式协变

心靈之曲

心靈之曲

发布时间:2026-01-22 18:59:22

|

281人浏览过

|

来源于php中文网

原创

Scala 中的类型推断是双向的,而非隐式协变

scala 并不默认对泛型类启用协变;看似“协变赋值”实为编译器基于左侧类型标注反向推断右侧泛型参数的结果,本质仍是不变型(invariant)行为。

在你提供的例子中:

case class Box[T](value: T)
val guppyBox: Box[Fish] = Box(new Guppy())

这段代码并未发生协变转换,也不依赖 Box 的协变声明(事实上 Box 是不变的)。真正起作用的是 Scala 强大的双向类型推断机制:当左侧已明确标注类型 Box[Fish] 时,编译器会将右侧 Box(...) 的类型参数 T 推断为 Fish,等价于:

val guppyBox: Box[Fish] = Box[Fish](new Guppy())

由于 Guppy 是 Fish 的子类型,new Guppy() 可以安全地作为 Box[Fish] 的 value: Fish 参数传入——这属于子类型替换(subtyping)在值层面的应用,与泛型类本身的变型(variance)无关。

⚠️ 关键验证:Box 确实是不变型的。以下代码将编译失败,明确证明它不支持协变赋值

// 编译错误:type mismatch
val boxGuppy: Box[Guppy] = Box(new Guppy())
val boxFish: Box[Fish] = boxGuppy // ❌ 不允许!Box[Guppy] 不是 Box[Fish] 的子类型

// 同样失败:
implicitly[Box[Guppy] <:< Box[Fish]] // ❌ 编译不通过

再看你的函数调用困惑:

IBM Watson
IBM Watson

IBM Watson文字转语音

下载
def unboxFish(fish: Box[Fish]) = ???
unboxFish(Box(new Guppy()))       // ✅ 成功:推断为 Box[Fish](new Guppy())
val guppyBox2 = Box(new Guppy())  // 推断为 Box[Guppy]
unboxFish(guppyBox2)              // ❌ 失败:Box[Guppy] ≠ Box[Fish]

第一行调用之所以成功,是因为编译器根据 unboxFish 的参数类型 Box[Fish],将 Box(new Guppy()) 推断为 Box[Fish];而第二行中,guppyBox2 因无左侧标注,被推断为最具体的 Box[Guppy],无法满足 Box[Fish] 参数要求。

✅ 正确做法(如需复用):

val guppyBox2: Box[Fish] = Box(new Guppy()) // 显式标注,确保类型一致
unboxFish(guppyBox2) // ✅

或显式指定类型参数:

val guppyBox2 = Box[Fish](new Guppy())

? 总结:

  • Scala 泛型默认是不变型(invariant),协变需显式声明(class Box[+T]);
  • “看似协变”的赋值行为,实为类型推断 + 子类型兼容性共同作用的结果;
  • 依赖推断时,务必注意上下文类型信息是否充分——缺失左侧标注易导致意外的具体类型推断;
  • 调试类型问题时,善用 implicitly[T <: u>

相关专题

更多
class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

467

2024.01.03

python中class的含义
python中class的含义

本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

13

2025.12.06

C++ 高级模板编程与元编程
C++ 高级模板编程与元编程

本专题深入讲解 C++ 中的高级模板编程与元编程技术,涵盖模板特化、SFINAE、模板递归、类型萃取、编译时常量与计算、C++17 的折叠表达式与变长模板参数等。通过多个实际示例,帮助开发者掌握 如何利用 C++ 模板机制编写高效、可扩展的通用代码,并提升代码的灵活性与性能。

10

2026.01.23

php远程文件教程合集
php远程文件教程合集

本专题整合了php远程文件相关教程,阅读专题下面的文章了解更多详细内容。

29

2026.01.22

PHP后端开发相关内容汇总
PHP后端开发相关内容汇总

本专题整合了PHP后端开发相关内容,阅读专题下面的文章了解更多详细内容。

21

2026.01.22

php会话教程合集
php会话教程合集

本专题整合了php会话教程相关合集,阅读专题下面的文章了解更多详细内容。

21

2026.01.22

宝塔PHP8.4相关教程汇总
宝塔PHP8.4相关教程汇总

本专题整合了宝塔PHP8.4相关教程,阅读专题下面的文章了解更多详细内容。

13

2026.01.22

PHP特殊符号教程合集
PHP特殊符号教程合集

本专题整合了PHP特殊符号相关处理方法,阅读专题下面的文章了解更多详细内容。

11

2026.01.22

PHP探针相关教程合集
PHP探针相关教程合集

本专题整合了PHP探针相关教程,阅读专题下面的文章了解更多详细内容。

8

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 4.1万人学习

Laravel---API接口
Laravel---API接口

共7课时 | 0.6万人学习

Golang云原生架构师课程
Golang云原生架构师课程

共49课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号