0

I pretty sure that the answer to the question in title is No. But i wrote a simple code and get a weird error when trying to compile. code:

open class Animal (val stttt:String, val str:String = "hjm") {
    open var fff: String = ""
    open var image = ""
    open val food = ""
    open val habitat = ""
    var hunger: Int? = 10
}

 class Hippo ( var strrr:Int = 7) : Animal("just") {
     override var image = "hippo.jpg"
     override var food = "grass"
     override val habitat = "water"
 }

fun main(args: Array<String>) {
    val hippo: Hippo? = Hippo()
    hippo?.hunger = 5
    println(hippo?.hunger)  // println(hippo?.hunger as Int?) works!!
}

the last line in code:

println(hippo?.hunger) // println(hippo?.hunger as Int?) works!!

makes the compiler display the following error:

smart cast to Int is impossible, because hippo?.hunger is a mutable property that could have been changed by this time

But, if i remove the following line the code is compiled:

hippo?.hunger = 5

Can someone explain me, what is wrong with this line of code that prevents the code from being compiled successfully?

enter image description here

Eitanos30
  • 1,331
  • 11
  • 19
  • Both lines work for me, your question isn't very clear. – Nicolas Oct 14 '20 at 17:54
  • @Nicolas, i have added a screen shot that shows that there is an error. Please help me to clarify the unclear things – Eitanos30 Oct 14 '20 at 18:00
  • @Alex.T, no it isn't. You can see that i'm using to safe call. The issue related to the line hippo?.hunger = 5 which for some reason (this is really the question) makes to an error in println call – Eitanos30 Oct 14 '20 at 18:07
  • @Alex.T, hi mate. After i have explain you with it isn't the same question. Can you close the duplicate request you have opened? – Eitanos30 Oct 14 '20 at 18:18
  • sure thing, just did – AlexT Oct 14 '20 at 18:19
  • @Alex.T can you please add the link you wrote before? i want to learn something from there :) .. I will delete the comment after i will get an answer from you – Eitanos30 Oct 14 '20 at 21:27
  • this was the link https://stackoverflow.com/questions/44595529/smart-cast-to-type-is-impossible-because-variable-is-a-mutable-property-tha – AlexT Oct 14 '20 at 21:32

1 Answers1

1

It runs just fine as posted: Kotlin Playground example

That error usually comes up where you've checked something isn't null, so you can treat it as a non-null type (Int in this case), but that doesn't work for vars because they can change, and could be null again - so you need to use something like hippo?.hunger?.let { bla bla } where the value gets assigned to a temporary val (it by default) which can't be changed.

I'm not sure why you're getting the error there, maybe it's trying to use the println(message: Int) call instead of the println(message: Any?) call for some reason? You can put the cursor on println and do ctrl+Q (or your equivalent) to find out which function it thinks it's calling.

But yeah, if the smart casting is messing you around, it's probably a bug. Casting to Int? like you're doing is one way of doing it, or doing the let/run thing might work too (hippo?.hunger.run(::println)).

Is your main block closed by the way? The curly brace is missing

cactustictacs
  • 17,935
  • 2
  • 14
  • 25
  • 1. as you thought it's trying to use the **println(message: Int)**. I can't understand why :( 2.When you say *But yeah, if the smart casting is messing you around, it's probably a bug* do you mean a bug in compiler or bug the way my head is thinking? :) 3. it works with *let*. since i don't know what is run and double :: i didn't try it 4. yes, my main block is closed – Eitanos30 Oct 14 '20 at 18:17
  • it is interesting how the line hippo?.hunger = 5 makes this problem. Didn't it reproduceable in your station? – Eitanos30 Oct 14 '20 at 18:20
  • The link I posted is from the Kotlin site where you can run some code, I pasted yours in and it didn't complain - it looks like it's an issue with the Kotlin plugin your IDE is using. For what it's worth, I pasted it into Android Studio (you're using IntelliJ, right? It's based on that) and it didn't complain, no error messages and it's using the ``Any?`` version. Try seeing if there are any updates to your plugins, maybe it's an issue that got fixed? – cactustictacs Oct 14 '20 at 18:26
  • ``run`` is the same as ``let``, except with ``let`` you're passing in a parameter (called ``it`` by default) and ``run`` uses it as a receiver (the variable becomes ``this`` in the function, basically). ``thing.run(::println)`` is just shorthand for ``thing.run { println(this) }``, sorry! I just like it because it's neat, you can do it with ``thing.let(::println)`` too (same as ``thing.let { println(it) }``. I'd use ``let`` if you're writing the lambda out and passing the parameter in, just looks better than passing in ``this``. Nothing to do with the question but sorry for the confusion! – cactustictacs Oct 14 '20 at 18:32
  • @ cactustictacs, updating plugin really solved the issue. I will approve your answer. You helped me a lot. Plugin :( ... Can you please explain what do you mean when saying: *writing the lambda out and passing the parameter in*, i will be more than happy to understand :) – Eitanos30 Oct 14 '20 at 19:33
  • Oh it's this stuff: https://kotlinlang.org/docs/reference/lambdas.html#instantiating-a-function-type , or this might be a good explanation: https://proandroiddev.com/the-difference-between-kotlins-functions-let-apply-with-run-and-else-ca51a4c696b8 - don't worry about it, ``let`` and ``run`` are the same thing, you just use the value in different ways and I just prefer ``thing.let { doSomething(it) }`` over ``thing.run { doSomething(this) }``, and I prefer ``thing.run { this.whatever() }`` (without the ``this``) over ``thing.let { it.whatever() }``. It doesn't really matter! – cactustictacs Oct 14 '20 at 23:28
  • @ cactustictacs thanks You!! When saying *thing.run { this.whatever() } (without the this)*, do you mean that this is redundant? – Eitanos30 Oct 15 '20 at 09:41
  • When you call a function on ``this``, like ``this.doThing()``, you don't need to explicitly include ``this`` - I just included it to show that when you use ``run`` the lambda acts on the object itself, if you use ``let`` the object is passed in as a parameter (called ``it``) instead. You can use whichever you like. You should read those links though, I can't really explain it in comments! – cactustictacs Oct 15 '20 at 16:11