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