最好的方法来处理这种情况下,“聪明的演员是不可能的”
我想知道处理这种情况的最好方法是什么
class Person(var name:String? = null, var age:Int? = null){ fun test(){ if(name != null && age != null) doSth(name, age) //smart cast imposible } fun doSth (someValue:String, someValue2:Int){ } }
调用doSth方法并确保名称和年龄nt为空的最简单方法是什么?
我正在寻找一个简单的方法,就像我只使用let的一个variables场景一样
name?.let{ doSth(it) }
你可以尽可能的嵌套let
:
fun test(){ name?.let { name -> age?.let { age -> doSth(name, age) //smart cast imposible } } }
另一种可能更容易遵循的方法是使用局部variables:
fun test(){ val name = name val age = age if(name != null && age != null){ doSth(name, age) } }
最后但并非最不重要的,考虑改变Person
是不可改变的如此:
data class Person(val name:String? = null, val age:Int? = null){ fun test(){ if(name != null && age != null){ doSth(name, age) } } ... }
为了使演员成为可能,你必须以某种方式制作一个值的本地副本。 在Kotlin中,最好的做法是明确的:
val name = name val age = age if(name != null && age != null){ doSth(name, age) }
let
函数隐藏这个抽象层,这不是最好的恕我直言。
有一个很好的小库,允许用多个variables编写let
like代码。 它是开源的,你可以在GitHub上find,它被称为Unwrap
基于自述文件的示例:
unwrap(_a, _b, _c) { a, b, c -> println("$a, $b$c") // all variables are not-null }
所有unwrap(...)
方法都标记为inline
所以不应该有使用它们的开销。
顺便说一句,这个lib还允许处理nah()
variables( nah()
方法)的情况。
如果你想把它看作一个“极端”,你可以在Pair
上定义一个扩展函数来隐藏你的逻辑:
fun Pair.test(block: (String, Int) -> Unit) { if(first != null && second != null) { block(first, second) } }
那么调用它会更简洁一些
(name to age).test { n, a -> println("name: $n age: $a") }
然而,它并不能真正帮助你(因为你可以把它定义成Person
类本身的一个函数),除非在整个项目中经常需要这种function。 就像我说的那样,似乎矫枉过正。
编辑你实际上可以使它(一点)更有用,通过完全通用:
fun Pair.ifBothNotNull(block: (T, R) -> Unit) { if(first != null && second != null){ block(first, second) } }
除了miensol的回答之外,还有多种方法可以将属性值复制到函数variables中以启用智能投射。 例如:
-
中介function:
class Person(var name: String? = null, var age: Int? = null) { fun test() = test(name, age) private fun test(name: String?, age: Int?) { if (name != null && age != null) doSth(name, age) //smart cast possible } fun doSth(someValue: String, someValue2: Int) { } }
-
匿名function:
class Person(var name: String? = null, var age: Int? = null) { fun test() = (fun(name: String?, age: Int?) { if (name != null && age != null) doSth(name, age) //smart cast possible })(name, age) fun doSth(someValue: String, someValue2: Int) { } }
-
默认参数:
class Person(var name: String? = null, var age: Int? = null) { fun test(name: String? = this.name, age: Int? = this.age) { if (name != null && age != null) doSth(name, age) //smart cast possible } fun doSth(someValue: String, someValue2: Int) { } }
有可能定义一个内联的方法,允许你采取N参数,以避免嵌套let
我(我基于我的答案)。
inline fun safeLet(p1: T1?, p2: T2?, block: (T1, T2)->R?): R? { return if (p1 != null && p2 != null) block(p1, p2) else null }
然后
fun test() { safeLet(name, age, {name, age -> doSth(name, age) //smart cast }); }