简体   繁体   中英

value of a variable not carried from one state to another in Kotlin

Beginner question - any idea why the value from lemonSize in SELECT is not carrying over to SQUEEZE when switching lemonadeState? Any help is greatly appreciated :)

The app/code is part of intro to Kotlin course by Google which is for creating a lemonade app that rotates between screens https://developer.android.com/codelabs/basic-android-kotlin-training-project-lemonade?continue=https%3A%2F%2Fdeveloper.android.com%2Fcourses%2Fpathways%2Fandroid-basics-kotlin-four%23codelab-https%3A%2F%2Fdeveloper.android.com%2Fcodelabs%2Fbasic-android-kotlin-training-project-lemonade#0

Here's where i think the problem is (I attached logs below that):

    // Default lemonSize to -1
    private var lemonSize = -1

    // Default the squeezeCount to -1
    private var squeezeCount = -1

    private var lemonTree = LemonTree()


when (lemonadeState) {
            SELECT -> {

                Log.d(TAG, "lemonadeState at beginning of SELECT *should be SELECT* lemonadeState = $lemonadeState")


                // Set the lemonSize (the number of squeezes needed) by calling the pick() method
                var lemonSize = LemonTree()//UPDATE
                Log.d(TAG, "randomly generated lemonSize using LemonTree -> lemonSize = $lemonSize")

                // Setting the squeezeCount (the number of times the user has squeezed the lemon) to 0.
                squeezeCount = 0
                Log.d(TAG, " setting squeezeCount to 0 -> squeezeCount = $squeezeCount")

                // Transition to the SQUEEZE state
                lemonadeState = SQUEEZE
                Log.d(TAG, "lemonadeState at bottom of SELECT *should be SQUEEZE* lemonadeState = $lemonadeState")
            }


            // TODO: When the image is clicked in the SQUEEZE state the squeezeCount needs to be
            //  INCREASED by 1 and lemonSize needs to be DECREASED by 1.
            //  - If the lemonSize has reached 0, it has been juiced and the state should become DRINK
            //  - Additionally, lemonSize is no longer relevant and should be set to -1
            SQUEEZE -> {


                Log.d(TAG, "at top of SQUEEZE *lemonSize should be 2-4* lemonSize = $lemonSize")
                Log.d(TAG, "at top of SQUEEZE *lemonadeState should be SQUEEZE* lemonadeState = $lemonadeState")

                //squeezeCount needs to be INCREASED by 1
                squeezeCount += 1

                //lemonSize needs to be DECREASED by 1.
                Log.d(TAG, "decreasing lemonSize by 1")
                Log.d(TAG, "lemonSize before decreasing by 1 lemonSize = $lemonSize")
                lemonSize = lemonSize - 1
                Log.d(TAG, "lemonSize after decreasing by 1 lemonSize = $lemonSize")

                //lemonSize = 0//REMOVE once done with testing
                //Log.d(TAG, "lemonSizeHere = $lemonSize ** REMOVE")

                //If the lemonSize has reached 0, it has been juiced and the state should become DRINK
                if (lemonSize == 0) {
                    lemonadeState = DRINK
                    //lemonSize = -1
                    Log.d(TAG, "lemonadeState when lemonSize == 0 lemonadeState = $lemonadeState")
                }
            }

/**
 * A Lemon tree class with a method to "pick" a lemon. The "size" of the lemon is randomized
 * and determines how many times a lemon needs to be squeezed before you get lemonade.
 */
class LemonTree {
    fun pick(): Int {
        return (2..4).random()
    }
}

Logs:

 2022-06-17 16:20:46.837 8549-8578/com.example.lemonade W/OpenGLRenderer: Failed to initialize 101010-2 format, error = EGL_SUCCESS
    2022-06-17 16:20:49.788 8549-8549/com.example.lemonade D/MainActivity: lemonadeState at beginning of SELECT *should be SELECT* lemonadeState = select
    2022-06-17 16:20:49.789 8549-8549/com.example.lemonade D/MainActivity: randomly generated lemonSize using LemonTree -> lemonSize = com.example.lemonade.LemonTree@5c31497
    2022-06-17 16:20:49.790 8549-8549/com.example.lemonade D/MainActivity:  setting squeezeCount to 0 -> squeezeCount = 0
    2022-06-17 16:20:49.793 8549-8549/com.example.lemonade D/MainActivity: lemonadeState at bottom of SELECT *should be SQUEEZE* lemonadeState = squeeze
    2022-06-17 16:21:04.177 8549-8549/com.example.lemonade D/MainActivity: at top of SQUEEZE *lemonSize should be 2-4* lemonSize = -1
    2022-06-17 16:21:04.179 8549-8549/com.example.lemonade D/MainActivity: at top of SQUEEZE *lemonadeState should be SQUEEZE* lemonadeState = squeeze
    2022-06-17 16:21:04.184 8549-8549/com.example.lemonade D/MainActivity: lemonSize before decreasing by 1 lemonSize = -1
    2022-06-17 16:21:04.186 8549-8549/com.example.lemonade D/MainActivity: lemonSize after decreasing by 1 lemonSize = -2

So you're creating a top-level variable called lemonSize that's initialised to -1 :

// Default lemonSize to -1
private var lemonSize = -1

That var is an Int which is inferred by the fact you assigned an integer value to it. This is meant to be size of your current lemon, right?

But inside your SELECT branch, you're doing this:

// Set the lemonSize (the number of squeezes needed) by calling the pick() method
var lemonSize = LemonTree()//UPDATE

There's two problems here - first, you're creating a new variable called lemonSize that only exists within the scope of those curly braces, the code that's executed when your state is SELECT . Whatever you do with that variable, it'll disappear once you exit that code block.

So when you reach the SQUEEZE branch, when that refers to lemonSize it's looking at the top-level one, which is still -1 . The lemonSize variable you created in SELECT is gone, and wouldn't be visible to the SQUEEZE block anyway.


So what you should be doing in SELECT is changing the value of that top-level 'lemonSize' variable (which is what you're doing for squeezeCount and lemonadeState anyway):

// no 'var' this time, we're setting the top-level one
// THIS LINE WON'T WORK THOUGH! see below
lemonSize = LemonTree()

and here's where you run into your other problem - this won't work, because you're calling LemonTree() which is the constructor for the LemonTree class. You're creating a LemonTree object and assigning it to the lemonSize variable - which as we saw earlier, has been inferred to hold an Int type. And a LemonTree is not an Int ! It can't go there

Your current code runs fine because you're basically creating a new local variable, that happens to be called lemonSize , and assigning a LemonTree to it - so you've created a variable with an inferred LemonTree type. And you don't do anything with it, so it's never a problem (although in your log you can see it prints out weird - com.example.lemonade.LemonTree@5c31497 means it's a LemonTree object with a reference ID, ain't a number!)


So like the comment above that line says, you really need to be calling pick() to get your lemonSize . And you could create a new LemonTree object right there to pick from - but you already put one in a top-level variable, lemonTree . You probably just want to use that, right?

In the end, you probably want to do this:

SELECT -> {
    // pick a new current lemon and record its size
    lemonSize = lemonTree.pick()
    ...
}

and now your top-level lemonSize state variable has a new value everything can see.

Hope that makes sense! There's a few concepts to get familiar with here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM