3

I have a piece of code:

class Test {
    fun test() {
        val fruit = if (Apple().doSomeThing() != null) {//1
            val result = Apple().doSomeThing()       //2
            //...use result
        } else if (Banana().doSomeThing() != null) {
            Banana().doSomeThing()
        } else {
            Peach().doSomeThing()
        }

    }

    internal open class Fruit

    internal class Apple : Fruit() {

        fun doSomeThing(): Boolean? {
            return false
        }
    }

    internal class Banana : Fruit() {
        fun doSomeThing(): Boolean? {
            return false
        }
    }

    internal class Peach : Fruit() {

        fun doSomeThing(): Boolean? {
            return false
        }
    }
}

It call Apple().doSomeThing() twice, can i declare a variable in if statement like this:?

var result :Boolean? = null
if((result = Apple().doSomeThing()) != null){
     //result.xxxx  //use result directly
}

And,how can i write test() method more gracefully!!

4 Answers 4

3

You can use the let function (doc) to avoid calling Apple().doSomething() twice and chain them with elvis operator ?: as below

    val fruit = Apple().doSomeThing()?.let {
        if (it) { // use the value of Apple().doSomething() here
            
        } else {
            
        }
    } ?: Banana().doSomeThing()?.let {
        if (it) {
            
        } else {
            
        }
    } ?: Peach().doSomeThing()?.let {
        if (it) {
            
        } else {
            
        }
    }

it within the scope of let in Apple().doSomeThing()?.let { } would have the value of Apple().doSomeThing() when it is not equal to null. And if Apple().doSomeThing() is equal to null, the elvis operator ?: would enable evaluating the next expression, that is Banana().doSomeThing()?.let { } and so on.

Sign up to request clarification or add additional context in comments.

Comments

2

First, a nicer version of test():

fun test() {
    val foo = Apple().doSomeThing()?.let { result ->
        //... use result
    } ?: Banana().doSomeThing()?.let { result ->
        //...use result
    } ?: Peach().doSomeThing()
}

Second, if you don't need to check all of the fruits in order, you can make much better use of inheritance:

fun test() {
    val fruit = listOf(Apple(), Banana(), Peach()).random()
    val result = fruit.doSomeThing()
}

interface Fruit {
    fun doSomeThing(): Boolean?
}

class Apple : Fruit {
    override fun doSomeThing(): Boolean? = false
}

class Banana : Fruit {
    override fun doSomeThing(): Boolean? = false
}

class Peach : Fruit {
    override fun doSomeThing(): Boolean? = false
}

Comments

2

Nope, but you can do so inside of when. The thing to note is that x is immutable.

when (val x = foo()) { ... }

Comments

1

As an addendum to the other answers: in the case where you're not doing anything else with the return values, it can simplify down to:

fun test() {
    val fruit = Apple().doSomeThing()
             ?: Banana().doSomeThing()
             ?: Peach().doSomeThing()

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.