Best way to handle such scenario where “smart cast is imposible”

前端 未结 7 772
鱼传尺愫
鱼传尺愫 2020-12-20 17:33

I wonder what is the best way to handle such scenario

class Person(var name:String? = null, var age:Int? = null){
    fun test(){
        if(name != null &am         


        
相关标签:
7条回答
  • 2020-12-20 18:15

    For the cast to be possible you have to make a local copy of the value somehow. In Kotlin this is best done explicitly:

    val name = name
    val age = age
    if(name != null && age != null){
        doSth(name, age)
    }
    

    The let function hides this behind an abstraction layer, which is not the best IMHO.

    0 讨论(0)
  • 2020-12-20 18:21

    There's a nice, little lib that allows for writing let-like code with multiple variables. It's open-source and you can find it on GitHub, it's called Unwrap

    Example based on readme:

    unwrap(_a, _b, _c) { a, b, c ->
        println("$a, $b$c") // all variables are not-null
    }
    

    All unwrap(...) methods are marked inline so there should be no overhead with using them.

    By the way, this lib also allows to handle situation when there are some null variables (the nah() method).

    0 讨论(0)
  • 2020-12-20 18:26

    In addition to miensol's answer there are various ways to copy property values into function variables to enable smart cast. e.g.:

    1. Intermediary 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. Anonymous 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. Default arguments:

      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) {
      
          }
      }
      
    0 讨论(0)
  • 2020-12-20 18:27

    I was having the problem while assigning text to textview with same problem description. All I did was putting double exclamation mark after the name of my textview. For example:

    var name:TextView?=null
    name = findViewById(R.id.id_name)
    name!!.text = "Your text"
    
    0 讨论(0)
  • 2020-12-20 18:34

    It is possible to define an inline method that allows you to take N parameters in order to avoid nesting lets (I'm basing my answer on this).

    inline fun <T1: Any, T2: Any, R: Any> safeLet(p1: T1?, p2: T2?, block: (T1, T2)->R?): R? {
        return if (p1 != null && p2 != null) block(p1, p2) else null
    }
    

    Then

    fun test() {
        safeLet(name, age, {name, age -> 
            doSth(name, age) //smart cast
        });
    }
    
    0 讨论(0)
  • 2020-12-20 18:37

    You can nest let as much as you like so:

    fun test(){
        name?.let { name ->
            age?.let { age ->
                doSth(name, age) //smart cast imposible    
            }
        }
    }
    

    Another approach, that might be easier to follow, is to use local variables:

    fun test(){
        val name = name
        val age = age
        if(name != null && age != null){
            doSth(name, age)
        }
    }
    

    Last but not least, consider changing Person to be immutable like so:

    data class Person(val name:String? = null, val age:Int? = null){
        fun test(){
            if(name != null && age != null){
                doSth(name, age)
            }
        }
        ...
    }
    
    0 讨论(0)
提交回复
热议问题