Extension function for Java class


#1

There is a Java class.

class JavaClass {
… a lot of static methods…
}

Can I create an extension function in my Kotlin code and call it like JavaClass.extensionFunction()?

I tried fun JavaClass.Companion.extensionFunction() but, obviously, the Companion cannot be found!


#2

Obviously you can’t extend the thing that does not exist. You will get the same error if you want to non-existing companion of kotlin class. There is a feature request somewhere in the tracker to automatically create empty companions in such cases, but it probably won’t work for java classes. Does it matter to you what namespace will you use to call static methods?


#3

Does it matter to you what namespace will you use to call static methods?

I want this extension function (in a Kotlin file) to seem like a static function (in a Java class).
There is no reason to do it but I am clearly experimenting around with Kotlin and I am wondering if this is possible.


#4

Kotlin extensions are not visible from java anyway.


#5

Well actually they are. Assuming you wrote the extension function in a plain file outside a class, the compiler creates a class called <filename>Kt and the function will be a static function with its first argument the receiver. When using Kotlin in a (decent) IDE, it detects that and hides the first parameter and lets you call as a normal function.


#6

I mean that they are not visible as extensions. The idea was to upgrade Java class with some functionality. This obviously won’t work. Maybe some IDE cheats could do that, but the code itself will be really ugly.


#7

I will not call the extension function from Java. I will call the function only from Kotlin. I wanted to seem (only to seem) like it is belonging in a Java class. I want to create an extension function and call it from Kotlin source only. As I know of, the extension functions can be called like this classInstance.functionName(). I want to create an extension function for a class and call it ClassName.functionName(). I want the extension function to resolve statically (as already does) and call it in a static way in my Kotlin source.


#8

Well then what you want is a plain regular extension function. Say you have you Java class in a .java file:

public class MyJavaClass {

    public String derp(){
        return "Hey mom!"
    }

    public MyJavaClass(){}
    
    // whatever...

}

In any Kotlin .kt file just write:

fun MyJavaClass.myExtension(){ // <-- here's the extension function definition. 
                               //     Notice your java class as receiver
    println("Hey! I'm an extension! Look: ${derp()}")
}

fun main(){
    val myJ = MyJavaClass()
    myJ.myExtension()
}

Output will be Hey! I'm an extension! Look: Hey mom!


#9

Based on your example I could explain myself better.
I don’t want to call the extension function like MyJavaClass().myExtension(). But, I want to call the extension function like MyJavaClass.myExteension() if possible.


#10

Indeed in the definition i wrote the receiver is the class not a particular instance of that class. On every object created from MyJavaClass you will be able to call myExtension()


#11

According to your example is it possible to create something like below?

fun main(){
//val myJ = MyJavaClass()
//myJ.myExtension()
MyJavaClass.myExtension()
}


#12

I think you have some sort of confusion on how classes and objects works. I’ll try to help. Have a look here:

fun main(){
    val myJ = MyJavaClass()
    myJ.myExtension() // <-- this is correct. Keep in mind that you have to declare 
                      //     `myExtension()` somewhere as i did in the previous example

    MyJavaClass.myExtension() // <-- this line is incorrect. You are calling a method
                              //     as it was static, but it's not.
}

Have a look at a more complete example:

// JAVA HERE

public class A {

    public String foo;

    public A(){
    }

}

// KOTLIN HERE

data class B(val foo: String)

fun A.extensionAlpha(){
    println("Hey I'm A and foo = $foo")
}

fun B.extensionBeta(){
    println("Hey I'm B and foo = $foo")
}

fun main() {
    val a = A()
    a.foo = "A"
    val b = B("B")
    a.extensionAlpha()
    b.extensionBeta()
}

The output will be:

Hey I'm A and foo = A
Hey I'm B and foo = B

You could even compact all of this this way (writing all in Kotlin so it’s more compact but it would work seamlessly using classes/interfaces from Java):

interface Foo {
    val foo: String
}

data class A(override val foo: String = "A"): Foo

data class B(override val foo: String = "A"): Foo

fun Foo.extension(){
    println("Hey I'm ${this::class.java.simpleName} and foo = $foo")
}

fun main() {
    val a = A()
    val b = B()
    a.extension()
    b.extension()
}

#13

I understand that.
To answer to my self about

Can I create an extension function in my Kotlin >code and call it like >JavaClass.extensionFunction() ?

the answer is no. There is no way to implement something like that.


#14

Yeah, but what’s the point of being able to add a static function to a class? Just create a static function somewhere else and you are good to go.


#15

If you could add a static function to a class it will be bonded to that class and it will not “pollute” the namespace at the package you are working. Probably, if a Companion object could be created automatically (as @darksnake mentioned) , this could be achieved.
I asked just to assure if this was not possible or if I have missed something!


#16

It is not possible unless the class already has a companion. In that case: fun Foo.Companion.bar() = "baz"


#17

You’re looking for this feature in the tracker
https://youtrack.jetbrains.com/issue/KT-11968