【问题标题】:Nested let blocks in KotlinKotlin 中的嵌套 let 块
【发布时间】:2023-03-15 22:40:01
【问题描述】:

在 Kotlin 中使用多个嵌套的 let 是一种好习惯,还是应该引入一个局部变量?有开销吗?

webView?.let { webview ->
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        webview.setLayerType(View.LAYER_TYPE_HARDWARE, null)
    } else {
        webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
    }

    webview.webViewClient = WebViewClient()

    webview.settings.let { settings ->
        settings.javaScriptEnabled = true
        settings.setSupportZoom(false)
        settings.builtInZoomControls = false
        settings.displayZoomControls = false
        settings.loadsImagesAutomatically = true
    }
}

【问题讨论】:

  • 提示:你可以使用let而不使用->,通过it引用对象
  • @pwolaq 但是因为它们是嵌套的,所以您必须非常小心,因为您可能会不小心引用错误的“它”。如果您要嵌套 let、run、apply、with、also,请确保明确命名事物(如 Sparrow318 所做的那样)。
  • @Mikezx6r 我不同意您的观点,只有当外部对象具有您想在内部对象上使用的相同方法/属性时才会出现问题 - 在其他情况下,IDE 会提示您出了点问题:)
  • @pwolaq。我说得太强烈了,但我认为我们同意在任何地方都依赖“它”是有风险的。如果两者都存在属性并且您打算引用外部而不是内部,则不会收到警告。如果您知道没有重叠,那就去做吧,但要注意风险。
  • 我习惯于命名值,出于同样的原因,您没有将变量声明为“temp1”。尤其是使用嵌套,可以更轻松地重新访问旧代码。

标签: android kotlin


【解决方案1】:

Kotlin 的创建者建议不要使用太多嵌套的let 调用,以实现更好的代码可读性和简洁性。在他们的《Kotlin in Action》一书中,他们说

当您需要检查null的多个值时,您可以使用嵌套 let 来电处理它们。但在大多数情况下,这样的代码最终会相当 冗长且难以理解。使用普通的if 通常更容易 表达式来检查所有值。

【讨论】:

    【解决方案2】:

    作为 zmbs13 答案的补充:

    由于您不需要对webview.settings 进行空检查,因此最好使用apply,它采用带有接收器的lambda:

    webview.settings.apply {
        // you refer to webview.settings with 'this', which can be omitted
        this.javaScriptEnabled = true // using this explicitely, in case there is another variable 'javaScriptEnabled' in this block
        setSupportZoom(false) // omitting this from here on
        builtInZoomControls = false
        displayZoomControls = false
        loadsImagesAutomatically = true
    }
    

    这使您的代码更加简洁,并避免了多次编写settingsit 的冗余。

    【讨论】:

      【解决方案3】:

      旁白。内部let 块可以用run 重写以获得更好的可读性:

      webview.settings.run {
          javaScriptEnabled = true
          setSupportZoom(false)
          builtInZoomControls = false
          displayZoomControls = false
          loadsImagesAutomatically = true
      }
      

      【讨论】:

        【解决方案4】:

        由于let 是内联的(参见:what is inlining,还有official docs),它的成本与自己声明局部变量完全相同。如果您将它与安全调用一起使用,它还会添加一个空检查,您也必须手动执行此操作。

        所以使用它基本上没有任何开销,只要你的代码对你来说足够清晰,就可以随意使用它。


        例如这样的代码:

        webview.settings.let { settings ->
            settings.javaScriptEnabled = true
            settings.setSupportZoom(false)
        }
        

        ... 将大致转换为与此 Java 代码等效的字节码:

        Settings settings = webview.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setSupportZoom(false);
        

        除了settings 可能会被称为像var10000 这样的通用名称,但这不是重点。关键是没有创建函数实例,也没有调用 let 函数或类似的东西,因此没有开销。

        对于未来的任何问题,您可以使用Kotlin plugin's bytecode viewer and decompiler 亲自检查。

        【讨论】:

          猜你喜欢
          • 2023-03-21
          • 2018-08-11
          • 2019-02-27
          • 1970-01-01
          • 2015-11-17
          • 1970-01-01
          • 2016-08-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多