Home > Blockchain >  How can I call Kotlin extension function with receiver from the Java static method?
How can I call Kotlin extension function with receiver from the Java static method?

Time:04-19

Probably I miss something very simple, but let's imagine I have this extension method in Kotlin:

fun Any.log(message: String) {
    println(this.javaClass.simpleName   message)
}

Is it possible to call it from the static method in Java class?

Note. From the regular instance method, I can do

MyExtensionsKt.log(this, "This is a log message")

But the static method doesn't have an object instance.

CodePudding user response:

You could just pass a random Object in:

MyExtensionsKt.log(new Object(), "This is a log message");

Of course, this will produce a log message that starts with Object, not the name of the current class.

To produce a log message that starts with the name of the current class, you would need to either create a new, temporary instance of the current class:

// suppose the static method is in "SomeClass"
MyExtensionsKt.log(new SomeClass(), "This is a log message");

or change the implementation of the log method to be a bit smart about its receiver. For example, if it is found that it is a Class, then just directly use its name as the prefix for the log message.

fun Any.log(message: String) {
    val prefix = if (this is Class<*>) {
        this.simpleName
    } else {
        this.javaClass.simpleName
    }
    println(prefix   message)
}

// then in SomeClass, you can do:

MyExtensionsKt.log(SomeClass.class, "This is a log message");

If you cannot do either of those things, then I would suggest that you not use a static method. How about the singleton pattern instead?

Example:

private static final SomeClass INSTANCE = new SomeClass();
public static final SomeClass getInstance() { return INSTANCE; }

// now you can have instance methods, and have access to "this"!

Side note:

Singletons are also how Kotlin's objects are implemented in the JVM.

object Foo {
    fun foo() { 
        this.log("This is a log message")
    }
}

When you call Foo.foo(), it may seem like you are calling a "static" method, but you are really just calling Foo.INSTANCE.foo(). Because of this, this is available in Kotlin objects.

CodePudding user response:

When you invoke that extension function in Kotlin code, it will look something like:

myObject.log("hello world")

To do the same thing from Java code, you would write:

MyExtensionsKt.log(myObject, "hello world")

The reason the code in your question works in an instance method is that this is a reference to the enclosing object. However, in a static method, there's no enclosing instance, so you'll need to provide some other object reference.

  • Related