代码之家  ›  专栏  ›  技术社区  ›  Kaveri

KOTLIN中的智能角色扮演与显式角色扮演有何不同

  •  1
  • Kaveri  · 技术社区  · 4 年前

    最近,我读到了关于由 is 运营商以及 as 或者更好 as? 其中的运算符用于显式转换。

    kotlin记录了物种的使用差异如下:-

    请注意,当编译器无法保证变量在检查和使用之间不能更改时,智能强制转换不起作用。 更具体地说,智能铸造根据以下规则适用:

    • val局部变量-除局部委托属性外,始终保持不变;

    • val属性-如果属性是私有的或内部的或支票 在声明属性的同一模块中执行。schlau 强制转换不适用于打开的属性或具有以下属性的属性 自定义getter;

    • var局部变量- 如果变量在 检查和使用 ,未在修改它的lambda中捕获, 并且不是当地委托财产;

    • var属性-从不( 因为变量可以在任何时候修改 其他代码的时间 ).

    请注意,当编译器无法保证时,智能强制转换不起作用 变量在检查和使用之间不能改变。

    上面写的有点令人困惑,因为 var 变量可以在初始化后更改,我找不到一个例子可以清楚地说明语句的实际含义。

    无论如何,有人能更容易地理解这一见解吗?

    确实如此 运营商提供了一些优化优势 作为 操作员,如果有的话?

    1 回复  |  直到 4 年前
        1
  •  7
  •   Sharp    4 年前

    智能演员阵容的想法是帮助你避免使用 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局部变量-如果变量在检查和使用之间没有被修改,则不会在修改它的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
            }
        }
    }
    

    就使用而言 作为 如果你看最后一个例子:

    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
            }
        }
    }
    

    您还可以使用 作为? 当你不确定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
    

    希望这些例子有所帮助,如果我需要进一步澄清,请告诉我。