Static extension methods in Kotlin

Static MethodsKotlin

Static Methods Problem Overview


How do you define a static extension method in Kotlin? Is this even possible? I currently have an extension method as shown below.

public fun Uber.doMagic(context: Context) {
    // ...
}

The above extension can be invoked on an instance.

uberInstance.doMagic(context) // Instance method

but how do I make it static method like shown below.

Uber.doMagic(context)         // Static or class method

Static Methods Solutions


Solution 1 - Static Methods

To achieve Uber.doMagic(context), you can write an extension to the companion object of Uber (the companion object declaration is required):

class Uber {
    companion object {}
}

fun Uber.Companion.doMagic(context: Context) { }

Solution 2 - Static Methods

This is what the official documentation says:

> Kotlin generates static methods for package-level functions. Kotlin > can also generate static methods for functions defined in named > objects or companion objects if you annotate those functions as > @JvmStatic. For example:

Kotlin static methods

class C {
  companion object {
    @JvmStatic fun foo() {}
    fun bar() {}
  }
}

> Now, foo() is static in Java, while bar() is not:

C.foo(); // works fine
C.bar(); // error: not a static method

Solution 3 - Static Methods

I actually had this exact question 30 minutes ago, so I started digging around and couldn't find any solution or workaround for this, BUT while searching I found this section on the Kotlinglang website that states that:

> Note that extensions can be defined with a nullable receiver type. Such extensions can be called on an object variable even if its value is null.

So then I had the craziest idea ever, why not define an extension function with a nullable receiver (without actually using that receiver) and then call it on a null object! So I tried that, and it worked pretty well, but it looked so ugly. It was like this:

(null as Type?).staticFunction(param1, param2)

So I went around that by creating a val in my extensions file of the receiver type that had a value of null and then use it in my other class. So, as an example, here is how I implemented a "static" extension function for the Navigation class in Android: In my NavigationExtensions.kt file:

val SNavigation: Navigation? = null
fun Navigation?.createNavigateOnClickListener(@IdRes resId: Int, args: Bundle? = null, navOptions: NavOptions? = null,
                                                navigationExtras: Navigator.Extras? = null) : (View) -> Unit {
    //This is just implementation details, don't worry too much about them, just focus on the Navigation? part in the method declaration
    return { view: View -> view.navigate(resId, args, navOptions, navigationExtras) }
}

In the code that uses it:

SNavigation.createNavigateOnClickListener(R.id.action_gameWonFragment_to_gameFragment)

Obviously, this isn't a class name, it is just a variable of the class type that has a null value. This is obviously ugly on the extension maker side (because they have to create the variable) and on the developer side (because they have to use the SType format instead of the actual class name), but it is the closest that can be achieved right now compared to actual static functions. Hopefully, the Kotlin language makers will respond to the issue that was created and add that feature in the language.

Solution 4 - Static Methods

You can create a static method with using Companion object like:

class Foo {
    // ...
    companion object {
        public fun bar() {
            // do anything
        }
    }
}

and then you can call it like:

class Baz {
    // ...
    private fun callBar() {
        Foo.bar()
    }
}

Solution 5 - Static Methods

Since I keep coming across this when searching, here's a different approach I haven't seen anyone mention that works in a static way and it works with generics!

Extension definitions:

// Extension function
fun <T> KClass<T>.doSomething() = /* do something */

// Extension Property
val <T> KClass<T>.someVal get() = /* something */

Usage:

MyType::class.doSomething()

MyType::class.someVal

As you can see, the trick is attaching the extension function to the KClass of the type instead since that can be referenced statically.

Solution 6 - Static Methods

Recomend you to look at this link. As you can see there, you just should declare method at the top-level of the package (file):

package strings
public fun joinToString(...): String { ... }

This is equal to

package strings;

public class JoinKt {
    public static String joinToString(...) { ... }
}

With constans everything are the same. This declaration

val UNIX_LINE_SEPARATOR = "\n"

is equal to

public static final String UNIX_LINE_SEPARATOR = "\n";

Solution 7 - Static Methods

I also required the ability to extend a Java object with a static method and found the best solution for me was to create a Kotlin object that extended the Java class and add my method there.

object Colour: Color(){
    fun parseColor(r: Int?, g: Int?, b: Int?) = parseColor(String.format("#%02x%02x%02x", r, g, b))
}

invocation:

val colour = Colour.parseColor(62, 0, 100)

Solution 8 - Static Methods

I'm also quite fond of having the possibility to add static extension methods in Kotlin. As a workaround for now I'm adding the exntension method to multiple classes instead of using one static extension method in all of them.

class Util    

fun Util.isDeviceOnline(context: Context): Boolean {
    val connMgr = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val networkInfo = connMgr.activeNetworkInfo
    return networkInfo != null && networkInfo.isConnected
}

fun Activity.isDeviceOnline(context: Context) = { Util().isDeviceOnline(context) }
fun OkHttpClient.isDeviceOnline(context: Context) = { Util().isDeviceOnline(context) }

Solution 9 - Static Methods

To create an extension method in kotlin you have to create a kotlin file(not a class) then declare your method in the file Eg:

public fun String.toLowercase(){
    // **this** is the string object
}

Import the function in the class or file you are working on and use it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRagunath JawaharView Question on Stackoverflow
Solution 1 - Static MethodsAndrey BreslavView Answer on Stackoverflow
Solution 2 - Static MethodslucasddanielView Answer on Stackoverflow
Solution 3 - Static Methodskyay10View Answer on Stackoverflow
Solution 4 - Static MethodsbbarmView Answer on Stackoverflow
Solution 5 - Static MethodsJustin WarkentinView Answer on Stackoverflow
Solution 6 - Static MethodsNisazhView Answer on Stackoverflow
Solution 7 - Static MethodsMatthew BatesView Answer on Stackoverflow
Solution 8 - Static Methodskosiara - Bartosz KosarzyckiView Answer on Stackoverflow
Solution 9 - Static Methodsdaniel.jbatizView Answer on Stackoverflow