Home > Software engineering >  Cant fix this error: "Smart cast to 'Node' is impossible, because 'node.left
Cant fix this error: "Smart cast to 'Node' is impossible, because 'node.left

Time:12-07

I keep getting this issue when using android studio (kotlin) and trying to design a decision app for android:

Smart cast to 'Node' is impossible, because 'node.left' is a mutable property that could have been changed by this time:104

Smart cast to 'Node' is impossible, because 'node.right' is a mutable property that could have been changed by this time:110

The code im trying to build is to make a small decision tree that i will expand on later. I am only trying to get the code to work and emulate it, i will design and such later.

This is my code:

package com.example.myapplication6

import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import android.view.Menu
import android.view.MenuItem
import com.example.myapplication6.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        setSupportActionBar(binding.toolbar)

        val navController = findNavController(R.id.nav_host_fragment_content_main)
        appBarConfiguration = AppBarConfiguration(navController.graph)
        setupActionBarWithNavController(navController, appBarConfiguration)

        binding.fab.setOnClickListener { view ->
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                .setAction("Action", null).show()
        }
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.menu_main, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        return when (item.itemId) {
            R.id.action_settings -> true
            else -> super.onOptionsItemSelected(item)
        }
    }

    override fun onSupportNavigateUp(): Boolean {
        val navController = findNavController(R.id.nav_host_fragment_content_main)
        return navController.navigateUp(appBarConfiguration)
                || super.onSupportNavigateUp()


        // A class to represent a node in the decision tree
        class Node {
            val data: String
            var left: Node?
            var right: Node?

            constructor(data: String, left: Node?, right: Node?) {
                this.data = data
                this.left = left
                this.right = right

        fun main() {
            // Create the root node of the decision tree with the question "Do you want to go to the social gathering?"
            val root = Node("Do you want to go to the social gathering?", null, null)

            // Create the left and right child nodes of the root node with the answers "Yes" and "No" respectively
            val yesNode = Node("Yes", null, null)
            val noNode = Node("No", null, null)

            // Set the left and right child nodes of the root node to the "Yes" and "No" nodes respectively
            root.left = yesNode
            root.right = noNode

            // Create the final level of nodes with the answers "Yes" and "No"
            val yesLeaf = Node("Yes", null, null)
            val noLeaf = Node("No", null, null)

            // Set the left and right child nodes of the "Yes" and "No" nodes from the previous level
            yesNode.left = yesLeaf
            yesNode.right = noLeaf
            noNode.left = noLeaf
            noNode.right = noLeaf

            // Create a list to store the decision tree nodes
            val nodes = mutableListOf(root)

            // Traverse the decision tree and print the question at each node
            while (nodes.isNotEmpty()) {
                val node = nodes.removeAt(0)
                println(node.data)



                // If the node has a left child, add it to the list of nodes
                if (node.left != null) {
                    nodes.add(node.left)
                }


                // If the node has a right child, add it to the list of nodes
                if (node.right != null) {
                    nodes.add(node.right)
                }
            }
        }


            }
        }


    }
}

I tried changing the node and defining it differntly but it didnt work.

CodePudding user response:

Kotlin has null-safety built into the compiler. This means it'll prevent you from trying to add nullable things (like node.left) to things that can't contain them (such as your MutableList<Node>).

"But I've done a null check just the line before!"

Yes, and usually that would be sufficient. But Kotlin knows that the left property of node is mutable, and so it could technically have been changed (from not null to null in between the null check and the add statement. That's what's generating the error.

You have two options here:

If you are very sure that there are no other threads changing nodes, you can tell the compiler "don't worry about it, I know this thing won't be null": nodes.add(node.left!!). However, this will cause a NullPointerException at runtime if you are wrong.

If you're not sure, you can simply only add the node if it's not null: node.left.let(nodes::add). This doesn't even require an explicit null check.

CodePudding user response:


    node.left?.let{
        nodes.add(it)
    }

    node.right?.let{
        nodes.add(it)
    }

  • Related