https://kotlinlang.org logo
Title
a

Andreas Sinz

09/12/2018, 9:16 PM
Is this a known issue?
fun main(args: Array<String>) {
    val foo = object {
        var foo: Int? = null
    }
    
    foo.foo = 5
    
    println(foo.foo) //Yields Smart cast impossible, because foo.foo is a mutable property ...
}
m

McEna

09/12/2018, 9:24 PM
Delete the ?
println signature does not recognize the null type, so either declare 'var foo: Int' or change the println call to 'println(foo!!.foo)'
that way you discard the null type
a

Andreas Sinz

09/12/2018, 9:27 PM
println(Any?)
is available, furthermore if i place
println
before
foo.foo = 5
it works
m

McEna

09/12/2018, 10:46 PM
At that point, type inference resolves to null, that's why it works. Once you mutate the variable, kotlin is unsure of which one use, because the actual type is Int or null, and Int matches one signature and null another.
I agree it should work as it is, but I've found kotlin's type inference is quite fragile because it scans the type each time the object is used
s

Sam

09/12/2018, 10:49 PM
println("${foo.foo}")
m

McEna

09/12/2018, 10:50 PM
for example, if you have a couple functions returning T where <T : SomeType> and then chain both methods in one T subclass (a generic fluent api), Kotlin will ask you to provide the actual type, but only at the last call
it will ignore all the previous inferences
So everytime you have several signatures, you have to provide the type. Kotlin will not choose the generic one like java does
d

Dico

09/13/2018, 5:28 AM
Can you give an example of that Francisco?
m

McEna

09/13/2018, 6:27 AM
Sure
Let's suppose we want a fluent API, so our setters will return the object. And we will have a huge hierarchy sharing some fundamental properties (like the android view hierarchy), so we need to make those setters generic, so every subclass will return an instance of itself.
public class Example extends somethingElse{ protected String Icon = ""; protected String title; public Example() { } public String getIcon() { return this.Icon; } public <T extends Example> T setIcon(String icon) { this.Icon = icon; return this; } public String getTitle() { return this.title; } public <T extends Example> T setTitle(String title) { this.title = title; return this; } } ExampleSubclass javaObject = new ExampleSubclass(1234, "abc").setTitle("atitle"; ExampleSubclass javaObject = new ExampleSubclass(1234, "abc").setTitle("atitle").setIcon("someAsset); ExampleSubclass().setTitle("OHOHOHO") ExampleSubclass().setTitle<ExampleSubclass>("OHOHOHO").setIcon("someAsset")
Java manages to run that code because it does not infer the type, so T is always resolved against the first declaration. Therefore, you can chain as much calls as you like, and the type declared at the left will be used as T.
Kotlin, in the other hand, ignores the previous statement everytime an assigment happens, forcing you to declare the type, despite the fact you already have it declared, because it solves the types at the last moment.
(is a very unlikely case since kotlin has apply() for these cases, but shows the difference)