android - 智能转换与 KOTLIN 中的显式转换有何不同
问题描述
最近我读到了由is
操作符执行的智能转换,以及用于显式转换的as
或更好的操作符。as?
kotlin 文档将它们的用法差异分类如下:-
请注意,当编译器不能保证变量在检查和使用之间不能改变时,智能转换不起作用。更具体地说,根据以下规则应用智能演员:
val 局部变量 - 总是除了局部委托属性;
val properties - 如果属性是私有的或内部的,或者检查是在声明属性的同一模块中执行的。智能转换不适用于开放属性或具有自定义 getter 的属性;
var local variables -如果变量在 check 和 usage 之间没有被修改,则不会在修改它的 lambda 中捕获,并且不是本地委托属性;
var 属性 - 从不(因为该变量可以随时被其他代码修改)。
请注意,当编译器不能保证变量在检查和使用之间不能改变时,智能转换不起作用。
上面写的有点混乱,因为var
变量可以在初始化后更改,我找不到可以清楚说明该语句的实际洞察力的示例。
无论如何,任何人都可以更容易地更好地理解这种洞察力吗?
如果有的话,运营商是否is
提供了一些优于as
运营商的优化优势?
解决方案
智能转换的想法是帮助您避免使用as
或as?
显式转换已经检查过的东西。至于上面的要点,这里有一些例子。
- val 局部变量 - 由于 val 是最终的(无法更改),在您进行检查后,该变量可以智能转换,因为它不能再次更改。
val a: Int? = 2
if (a is Int) {
// 'a' is smart cast to Int
val b = a * 2 // b is also Int
}
- val 属性 - 如果直接访问(通过默认 getter),则可以进行智能转换。如果通过自定义 getter,这不是因为我们不知道它被修改过。
class Test {
val a: Int? = 2;
}
class TestGetter {
val a: Int? = 2
get() = field * 2
}
// Usage
val test = Test()
val testGetter = TestGetter()
if (test.a is Int) {
// 'test.a' is smart cast to Int
val b = test.a * 2
}
if (testGetter.a is Int) {
// smart cast is impossible, 'testGetter.a' is still Int?
val b = testGetter.a * 2 // can't happen because we don't know whether 'a' was changed by the custom getter or not (the getter could give unstable values)
}
- var local variables - 如果变量在检查和使用之间没有被修改,则不会在修改它的 lambda 中捕获,并且不是本地委托属性;
var a: Int? = 2
if (a is Int) {
// 'a' was not changed, so it can be smart cast to Int
val b = a * 2 // b is also Int
}
var c = 4
if (c is Int) {
c = null
// 'c' was changed between the check and the usage, we cannot smart cast it anymore
val b = c * 2 // won't work
}
var 属性 - var 总是可以被代码中的其他东西修改,所以智能转换不起作用。
class Example {
var a: Int? = 2
fun test1() {
if (a is Int) {
// smart cast is impossible because we don't know whether 'a' was changed by some other code/function
val b = a * 2 // won't work
}
}
}
就使用as
而言,如果您查看最后一个示例:
class Example {
var a: Int? = 2
fun test1() {
if (a is Int) {
// smart cast is impossible because we don't know whether 'a' was changed by some other code/function
val b = a as Int * 2 // this WILL work because we forcefully cast it to Int, but if a is null there will be an exception in runtime
}
}
}
as?
当您不确定 var 是否可以转换为某些东西时,您也可以使用。如果没有,它只会给你一个空值。例如:
val a: Double = 2.0
val b = a as? String // 'b' will be 'String?', in this case initialized to 'null' since 'a' cannot be cast to it
val c: Int? = 2
val d = c as? Int // 'd' will be '2' but still 'Int?' since 'as?' always makes the variable nullable
希望这些示例有所帮助,如果我需要进一步澄清,请告诉我。
推荐阅读
- r - R:识别一列中的非 NA 值并创建数据框,其中选择了另一列基于行的值
- mongodb - MongoDB - 查找两个集合之间的差异
- flutter - 在另一个屏幕中访问 FutureProvider 时遇到问题
- python - numpy 相当于 list.index
- database - 用于树结构数据的图形数据库或关系数据库
- oracle - 日志返回一个有趣的函数的结果
- docker - 等到 docker 容器在 circleci 中就绪
- webpack - 显示 webpack 处理的所有文件
- c++ - 为动态数组预留较大的虚拟内存空间,并根据需要映射核心内存
- unit-testing - 在 Golang 中使用不同的值多次运行单元测试