https://kotlinlang.org logo
m

Marc

09/07/2023, 1:42 PM
I have an interface that defines an extension member function like this in my code:
Copy code
class Context

sealed interface Interface {
    fun Context.test(): String

    data object Sub1 : Interface {
        override fun Context.test() = "D"
    }

    data class Sub2(
        val i: Int
    ) : Interface {
        override fun Context.test() = "E"
    }
}
I now wanted to call the correct implementation of the
test()
function depending on what subtype of `Interface`a variable of mine is. While implementing that I noticed that the following compiles:
Copy code
with(Context()) {
    test()
}
Even though I don't provide an implementation of `Interface`anywhere, it still compiles just fine and just always uses the implementation in
Sub1
. This seems wrong to me. It kind of makes sense since the implementation in the data object does not have additional dependencies and it stops compiling when I change `Sub1`to be a class instead, but the fact that it works is still really weird. The part that I don't understand at all is that it does compile and run just fine in my Compose Multiplatform app, but when I run it in the playground (https://pl.kotl.in/aC93OsPqq) it does not work and I need to provide an instance of
Interface
, which is the behaviour I would expect. Can someone explain this discrepancy to me?
a

ascii

09/07/2023, 1:53 PM
Your IDE is auto-importing Interface.Sub1
Depending on your UI theme, such "static" imports are italicized
m

Marc

09/07/2023, 1:56 PM
Ah, I see. So basically as long as the import can be statically resolved (inside nested interfaces/objects, but not classes) and you just import the implementation, it will just run the static version? It was very confusing to me in this case because I didn't expect it to be able to just use an overriden function implementation like this.
a

ascii

09/07/2023, 1:57 PM
You can do
Interface.Sub1.test()
manually, and that's what the IDE assumes you want to do. It's the only thing that fits, so the IDE imports it.
object
is already an instance, you don't need to instantiate it. When decompiled to Java, this is what it looks like:
Copy code
public final class Sub1 {
    public static final Sub1 INSTANCE
    static { INSTANCE = Sub1() }
}
Which is why something like
Interface.test()
or
Sub2.test()
won't work. You have to instantiate
Sub2(i)
first, then call
test()
on it.
m

Marc

09/07/2023, 2:02 PM
It makes sense to me now, I didn't think about the auto import. The behaviour of importing one of multiple implementations of the function and calling it just did not occur to me at all... Thanks a lot for explaining.