Search code examples
javaandroidkotlinkotlin-inline-class

Kotlin inline class that implements interface under the hood


In kotlin vesion 1.3.0 inline classes were made available for developers.

"Normal" inline classes are promised not to be a real objects at runtime but exist only at compile time for type checking.

So for instance

inline class MyWrapper(val someString: String)

fun consumeMyWrapper(myWrapper: MyWrapper)

should be compiled to java equivalent of the following:

public void consumeMyWrapper~blabla(String myWrapper) 

However this also works:

interface A {

    fun doJob(b: B)
}

inline class C(val self: D): A {

    override fun doJob(b: B)
}

So I'm wondering how exactly does this compile. I don't know bytecode so I'm asking for general principle.

However if such an object which should implement certain interface does not exist at runtime, then somebody else must implement the interface. Will it be the receiver of an inline class? What will happen if the receiver happened to be of unmodifiable type (from other already compiled lib for instance)?

Reasons why I have these concerns have to do with a problem I stumbled upon recently. I needed a cleaner way to communicate Fragment with Activity on a massive project. The old way was just saying activity as? MainActivity which is not "very clean". So I defined this interface:

interface ActivityDelegate {

    val view: View

    val routing: Routing

    interface View {
       // All common view related stuff
    }

    interface Routing {
       // BottomNavigtion related stuff
    }
}

And implemented it as follows:

class MainActivity : Activity(), ActivityDelegate {

    override val view by lazy { MainActivityView(this) }

    override val routing by lazy { MainActivityRouting(this) }
}

internal inline class MainActivityView(val self: MainActivity): ActivityDelegate.View 

internal inline class MainActivityRouting(val self: MainActivity): ActivityDelegate.Routing

I used this approach with inline classes to move some logic out from MainActivity and delegate responsibilities.

So my concerns are whether or not this is appropriate to have inline class here. Does it make a difference when used in this particular scenario?


Solution

  • "Normal" inline classes are promised not to be a real objects at runtime

    Not quite:

    However, sometimes it is necessary to keep wrappers around. As a rule of thumb, inline classes are boxed whenever they are used as another type.

    In particular, it is the inline class itself which implements the interface. And when you use the inline class with the interface as the static type is exactly one of the cases when it gets boxed (as demonstrated in the examples linked above). In your case I believe it will box and you don't get any benefit from it being inline.