5

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?

M'aiq the Coder
  • 762
  • 6
  • 18

1 Answers1

9

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>()
zsmb13
  • 85,752
  • 11
  • 221
  • 226
  • Now I see. Thanks. I think all three solutions are good. I think I will come down to creating a companion object (like you said) in every class and use it the simple way like `StateA.transformName()`. I'll log some things to make sure it doesn't cause any problems but the other two solutions are also great in terms of code practice. Thank you a lot, sir! – M'aiq the Coder Oct 10 '19 at 07:45
  • Or maybe not. If I think more about it, the cleaner solution is your last one with the reified. I don't think it's actually a good practice to add some useless companion objects just for some function. – M'aiq the Coder Oct 10 '19 at 07:49
  • 1
    It's not a bad practice to add a companion object in a class to put extensions on it like that (it's why `kotlin.Boolean` has a companion, for example), but yes, it might be tedious to do it for several classes, only to let them be used with this one extension. – zsmb13 Oct 10 '19 at 08:38