KMM Oddity #1: Interface methods with underscores
Kotlin Multiplatform attracts more and more developers every day. Especially after the technology transitioned to the Alpha stage. On its way to Beta, KMP removes all major hassles (Memory Model, for example).
Nonetheless, you can still find “a few” more minor bugs and oddities reported in Kotlin’s YouTrack. They aren’t blockers for using KMP in your production application but may cost you several hours of wondering what and why is happening in your mobile application (mainly on iOS).
I faced many such issues myself since I’ve started using Kotlin Multiplatform Mobile two years ago. In this series of articles, I’ll share my favorite oddities of KMM with explanations and workarounds (if possible).
Kotlin/Native Obj-C interop
Shared KMM modules are written in Kotlin, hence can be used in Android native applications as it is. On iOS, it’s more complicated because of Objective-C and Swift, which can’t directly use Kotlin code.
Kotlin/Native plugin compiles shared KMM modules to iOS frameworks, which contain binary and Obj-C header. You can find them in the build folder of the shared module, under
Many concepts of Kotlin don’t exist in Obj-C, so specific shortcuts and workarounds need to be applied to make it work. It is where some oddities start appearing.
Interface methods naming clash
Let’s say we have two types of pets —
Cat, which we need to feed with some specific
Food. In Kotlin, we could represent that with two interfaces, each having an internal (embedded)
It works perfectly well in Android, but on iOS
Dog will have
eat(food_:) method instead of
eat(food:). Where does that underscore suffix come from? And why do we need it?
It looks like Kotlin/Native compiler thinks there will be a clash between
eat(food:) methods of
Cat interfaces, so it’s safer to make them different by implicitly adding an underscore to the 2nd one.
I’m not sure it will become a problem and if it can be fixed from the Kotlin/Native side. But it becomes pretty annoying when we add a few more animals because each will have one more underscore.
A more realistic example would be about
View interface in MVP architecture, where each class will have
Is the problem in embed classes?
So maybe it’s the embed
Food class that drives K/N compiler crazy? Let’s try to extract both classes alongside pets.
After compiling the iOS app, we see that the actual content of the Obj-C header didn’t change even a little, so the problem isn’t about embedded classes in interfaces.
What if cats and dogs share the food?
Well, that’s not a great idea, but let’s try to be sure.
Surprisingly, it solves the issue. So if methods share the same arguments, the K/N compiler handles them as we expect. But sharing food between dogs and cats may be dangerous, so let’s try finding another solution.
Is the problem in interfaces?
Let’s try converting interfaces to abstract classes.
And yes, both
eat(food:) methods in
Dog are named as expected. It seems to be a much better way to solve the issue.
abstract classes to just
classes is an option as well.
The next time you see some unexpected trailing underscores in your KMM interface method names, you can be sure that it’s not critical, and there are multiple workarounds to resolve the issue quickly.
There is an obvious solution, which wasn’t interesting enough to describe in the article itself, but which you may consider too — rename clashing methods or arguments to calm down the K/N compiler.