I'm confused by this behavior ```sealed interface ...
# getting-started
y
I'm confused by this behavior
Copy code
sealed interface Foo {
    data class FooClass(val n: Int) : Foo {
        fun hello() { /* ... */ }
    }

    data object FooObject : Foo {
        fun hello() { /* ... */ }
    }
}

fun main() {
    val foo = getFoo()
    when (foo) {
        is Foo.FooClass -> foo.hello() // resolves
        Foo.FooObject -> foo.hello() // does not resolve
    }
}
why doesn't this resolve? am I supposed to call it as
Foo.FooObject.hello()
?
sorry, copy/paste error
my apologies
j
Ah I was too late to remove my comment 😅
y
NOW it's right heh
j
I believe the check on object without
is
might not restrict the type itself. Have you tried with
is
?
thank you color 1
y
you're right!
j
That being said, you don't really need the
foo
variable anymore if you already know it's this specific object, so you can indeed simply use the object with
Foo.FooObject.hello
Also, it might be better to lift the
hello
declaration up to the
Foo
interface, so you don't even need a
when
at all
y
so, first of all, I think this behavior is kind of peculiar and I would expect the flow-sensitive typing here to conclude that
foo
is
Foo.FooObject
even without the
is
. the compiler kinda left me in the dark here as for hoisting the
hello
to the interface, I wish I could do that but unfortunately the real version of `FooClass`'s
hello
takes additional context as parameters
j
I see. Yeah I agree that the behavior you're seeing is surprising. It might be worth reporting a YT issue to check if the Kotlin team considers this a bug or not
y
I'll see about doing that. thanks again
j
This might be a wider issue than just objects. For instance if the static type is
Any
and you check for the value 42, we could get flow typing and restrict to
Int
.
Ah I think I understand why we can't restrict the type here. Just because
foo
is equal to a value doesn't mean that it's of the same type, actually!
What if your class
FooClass
overrides
equals
and returns
true
for
FooObject
values? It would be incorrect to consider that the type is
FooObject
So if you really want to check on types, you should use
is
- it's not the same check. It uses
instanceof
, not
equals
y
right! I was about to mention how
Copy code
if (foo == Foo.FooObject) { /* still can't use foo as `FooObject` here */ }
also not working, suggests that this is likely intentional
👌 1
yeah. equality is definitely not the same as
instanceof
imo the fact that IntellIJ "when branch autofill" assist fills objects as equality checks instead of
is
checks, also adds to this confusion (it confused me)