Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a Kotlin extension function on a class?

I have a pretty short question about an extension function that would help clear some of my code. Basically I have some transformations on the hashCode of a class name and I want an extension function to do the transformations.

Example:

Getting the name hashCode: StateA::class.java.name.hashCode() where StateA is a simple class.

I want to the extension function like:

    fun Class<*>.transformName(): String {
       var hashString = this.javaClass.name.hashCode()

       //Do my stuff on that hashString

       return hashString
    }

But this doesn't seem to work. When I apply the extension function with StateA.transformName(), the function gives me an error with Unresolved Reference.

I tried various things like applying the function to StateA::class or having the hashString equal to this::class.java.name.hashCode() but nothing works. Any tips?

like image 772
M'aiq the Coder Avatar asked Oct 10 '19 07:10

M'aiq the Coder


People also ask

Can we write extension function inside a class body?

This is done via special declarations called extensions. For example, you can write new functions for a class or an interface from a third-party library that you can't modify. Such functions can be called in the usual way, as if they were methods of the original class. This mechanism is called an extension function.

How extension function works internally in Kotlin?

Are you using Intellij IDEA or Android Studio? Open a Kotlin file that has extension functions, go to Tools -> Kotlin -> Show bytecode, and from the bytecode window that pops up choose Decompile. You'll see what the Java analog of that code looks like and it'll quickly become apparent what the trick is!


1 Answers

You can't really achieve the StateA.transformName() syntax, as StateA just on its own refers to the companion object inside that class. So to get that syntax, you'd need to have a companion object inside every class that you want to use this extension on.

What you can do in a very general way is get the KClass that describes your class first. This gives you an object (the KClass instance) that you can then call an extension on:

fun KClass<*>.transformName() {
    val clazz: Class<*> = this.java
    clazz.name.hashCode()
}

StateA::class.transformName()

Another approach, which is less verbose on the call site could be a generic function like this, where the reified keyword allows you to access the concrete class that was used as the generic type parameter inside the function:

inline fun <reified T> transformName() {
    val clazz: Class<*> = T::class.java
    clazz.name.hashCode()
}

transformName<StateA>()
like image 96
zsmb13 Avatar answered Nov 14 '22 23:11

zsmb13