最好的方法来处理这种情况下,“聪明的演员是不可能的”

我想知道处理这种情况的最好方法是什么

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中以启用智能投射。 例如:

  1. 中介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) { } } 
  2. 匿名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) { } } 
  3. 默认参数:

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