应该使用Kotlin标准函数(运行,让其应用,还是应用它们)来拆开可选选项,或者应该为此使用单独的方法?

时间:2019-04-25 12:47:58

标签: android kotlin optional conventions

当我看到标准函数run, let, also, apply时,我看到它们在整个代码库中都用在不同的情况下,因此发现了两件事:

所有这四个方法都打开了可选的包装,但是可以这么说,它们也具有不同的返回类型和不同的上下文。

读入Kotlin's Null-Safety documentation,看来在Kotlin中解开可选内容的推荐方法是使用let

关于这四种方法的背景知识:

val string = ""
val thing: String = string.apply { length } + string.also { it.length }
val other: Int = string.run { length } + string.let { it.length }

由于四种方法的返回类型,此代码将编译。有关此方法的更多信息,您可以查看this blog post

但是,由于所有这四种方法都取消了可选方法的包装,因此我们团队中的某些开发人员更愿意编写:

textView?.run {
someLongMethod(
        text = text,
        blah = blah,
        blah2 = blah2
    )
}

textView?.let {
someLongMethod{
        text = it.text,
        blah = it.blah,
        blah2 = it.blah2
    )
}

前面提到的首选项在样式上是明智的,并且也是一致的,因为在两种情况下,我们都没有利用letrun块的返回类型。此外,使用run可以解开可选的textView,还可以消除多余的it.,而不必在我的方法调用中一遍又一遍地写出来。

我的论点的全部前提是基于这样的事实:在设计上和传统上,可以接受上述操作。

如果是这样,在这种特定情况下,用let替换also或用run替换apply不会导致更改,既不会在其各自的块内,也不会导致更改有任何副作用。

因此,我觉得使用这四种方法中的任何一种来解开可选选项都可能导致团队内部开发人员之间出现明显的不一致,并且在这种情况下,除了个人选择之外,没有论据可以保证一个使用另一个。 / p>


因此,我提出了以下两个扩展名(尽管第二个可以使用更好的名称):

@UseExperimental(ExperimentalContracts::class)
inline fun <T, R> T.unwrap(block: (T) -> R) {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
}

@UseExperimental(ExperimentalContracts::class)
inline fun <T, R> T.unwrapInScope(block: T.() -> R) {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
}

这样,先前编写的代码块将变为:

textView?.unwrapInScope {
someLongMethod(
        text = text,
        blah = blah,
        blah2 = blah2
    )
}

并且由于我们没有利用返回类型,因此在这种情况下,最好使用扩展名。当unwrap优先于let时,将使用另一个run扩展名。

这当然只是我的论点。但是,我想知道是否缺少某些东西?首先,我们不应该使用run来包装可选项目吗?还是Kotlin应该采用不同的方法来消除这种差异?

0 个答案:

没有答案