kotlin - Kotlin:在哪些情况下会发生隐式转换?
问题描述
我是 Kotlin 的初学者。我最熟悉 Python,在进入 Kotlin 之前,我刚刚通读了基本的 Java 教程https://docs.oracle.com/javase/tutorial/java/index.html 。
在阅读 Kotlin 文档的这一部分时,我想到了一个问题
https://kotlinlang.org/docs/reference/basic-types.html#explicit-conversions
我从文档的上述部分了解到的是:
- 对于 assignments
=
,会发生隐式类型转换。如果左侧的类型是超类型或右侧类型的相同类型,则代码将编译。否则就是编译错误。在 and 的情况下Int
,Long
它们都是 的子类型,Number
但它们都不是彼此的子类型,因此隐式转换不起作用。因此,我们需要使用 .toLong() 或 .toInt() 等方法来显式转换它们。
然后当我读到这部分
val l = 1L + 3 // Long + Int => Long
我开始想知道在这种情况下是否会发生隐式类型转换。
文档说这与运算符重载有关。这个运算符重载是如何在后台实现的?我试图在 Github https://github.com/JetBrains/kotlin/blob/master/core/builtins/native/kotlin/Primitives.kt上找到源代码,但这里只声明了函数但没有实现。我在哪里可以找到实现?
似乎操作重载实际上并没有执行类型转换。我们是否只是实现了所有可能的具有相同名称但参数类型签名不同的函数,以便推断类型,然后选择具有匹配签名的函数?
还有一个普遍的问题:在 Kotlin 中,隐式转换究竟在哪些情况下发生?
解决方案
对于赋值 =,会发生隐式类型转换。如果左侧的类型是超类型或右侧类型的相同类型,则代码将编译。
作业在这方面并不特别。更一般地,如果表达式的预期类型是超类型或与实际类型相同,则代码编译;只是赋值右侧的预期类型是左侧的类型。我不会说插入了隐式转换,但是如果您这样看,我认为不会有任何问题。
我们是否只是实现了所有可能的具有相同名称但参数类型签名不同的函数,以便推断类型,然后选择具有匹配签名的函数?
是的,完全正确(对于这种情况)。如果要支持原始类型,则需要为所有这些类型提供重载。
就解析和类型检查而言,这1L + 3
只是一个方法调用(特别是`Long.plus(Int): Long),不涉及隐式转换。但是这些方法内置在编译器中以进行特殊处理,这就是您看不到实现的原因。
它变成了两个字节码指令i2l
(“将一个 int 转换为一个 long”)和ladd
(“添加两个 long”),但这不是你应该关心的事情,或者很长时间都不应该关心。
还有一个普遍的问题:在 Kotlin 中,隐式转换究竟在哪些情况下发生?
智能转换是 Kotlin 最接近隐式转换的方法,但它们与其他语言中的 ics 有很大不同,因此我不会使用这个名称。所以我会说永远不会。
推荐阅读
- docker - 如何使用 Let's Encrypt 和在 docker 容器中运行的 GitLab
- css - Css内边界半径
- c# - C#如何从字符串呈现标签助手
- flutter - 在 Dart 的列表中使用 map 或 for 循环有什么区别吗?
- r - 如何对数据框中的行进行排序以获取 R 中某些列的最大净值和符号
- python - Python - 计算 NumPy 数组中元素和邻居的平均绝对差
- reactjs - 手动刷新页面时如何强制app.js中的useEffect在其他组件的useEffect之前加载
- django - AWS RDS 重命名数据库名称
- python - 如何识别 kmeans 集群图中的标签?
- apache-spark - 与 Pythonic 版本相比,为什么在 PySpark 中转换后我会丢失数据框中的一些记录?