【问题标题】:Kotlin equivalent of Swift's defer keywordKotlin 相当于 Swift 的 defer 关键字
【发布时间】:2018-07-18 21:09:41
【问题描述】:

在 Kotlin 中是否有类似的东西提供与 Swift 关键字“defer”相同的功能?

defer 关键字的作用是,它确保 defer 块中的代码在从函数返回之前得到执行。

下面是假设 Kotlin 中存在 defer 关键字的示例。

    class MyClass {

        var timeStamp = 0L

        fun isEdible(fruit: Fruit): Boolean {
          defer { 
           timeStamp = System.currentTimeMillis()
          }
          if (fruit.isExpired) {
             return false
          }
          if (fruit.isRipe) {
            return true
          }
          return false
        }
     }

在上述情况下,无论函数在什么时候返回,defer 中的块都会在函数结束之前被执行并且时间戳的值会被更新。

我知道 Java 有 finally {} 关键字与 try{} catch{} 一起使用,但它并不是 defer 所提供的。

【问题讨论】:

  • 我不使用 swift,但在功能上延迟一个异步线程,在方法返回之前“加入”主线程?
  • @Pawel defer 在 Swift 中只是在离开当前范围(例如退出函数)后执行 defer 块。
  • try/finally,我想
  • 我第二个 @Alexander:快速浏览一下 Kotlin 的语法确实指向 finally 块。我记得很久以前读过一篇关于 Swift 的defer 的文章,将其描述为“tryfinally 做得对”。所以我相信你可能得到的答案不是你正在寻找的答案(至少是 Kotlin 原生)。
  • @rgv 您的问题得到解答了吗?

标签: android swift kotlin keyword


【解决方案1】:

在 Kotlin 中没有这样的关键字,但您可以自己构建一个工作原理非常相似的构造。像这样的东西(请注意,这不处理延迟块中的异常):

class Deferrable {
    private val actions: MutableList<() -> Unit> = mutableListOf()

    fun defer(f: () -> Unit) {
        actions.add(f)
    }

    fun execute() {
        actions.forEach { it() }
    }
}

fun <T> defer(f: (Deferrable) -> T): T {
    val deferrable = Deferrable()
    try {
        return f(deferrable)
    } finally {
        deferrable.execute()
    }
}

那么你可以这样使用它:

class MyClass {

    var timeStamp = 0L

    fun isEdible(fruit: Fruit): Boolean = defer { d ->
      d.defer { 
       timeStamp = System.currentTimeMillis()
      }
      if (fruit.isExpired) {
         return false
      }
      if (fruit.isRipe) {
        return true
      }
      return false
    }
}

【讨论】:

  • 有趣的方法! Try/Finally 绝对是更合适的选择,但这很整洁。
  • 您也可以将顶级函数更改为fun &lt;T&gt; deferBlock(f: Deferrable.() -&gt; T),并在内部仅使用defer 而不是d/it.defer
  • @AlexeyRomanov 我想过这个问题,但我决定不想将this 的值从MyClass 更改为Deferrable
  • 很公平,只是作为一个选项提及。
  • @Alexander 我将实现更改为使用 try/finally。即使函数体抛出异常,这也将使延迟块执行。不过,我真的不知道 Swift 如何处理延迟块中的异常。我的快速谷歌搜索没有找到任何东西。你知道吗?
【解决方案2】:

最接近的等价物是try/finally。如果没有抛出异常,则不需要catch

try {
    println("do something")
    // ... the rest of your method body here
}
finally {
    println("Don't forget about me!");
}

在 Swift 中,defer 通常用于确保您不会忘记清理某种资源(文件句柄、数据库连接、共享内存映射等)。为此,Kotlin 使用with,它采用闭包,资源作为参数传递给该闭包。资源在闭包的生命周期内有效,并在结束时自动关闭。

FileWriter("test.txt")
  .use { it.write("something") }
// File is closed by now

【讨论】:

    猜你喜欢
    • 2016-06-21
    • 1970-01-01
    • 2010-12-10
    • 1970-01-01
    • 2011-11-01
    • 1970-01-01
    • 2013-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多