Invoke Operator & Operator Overloading in Kotlin

The most way to use a invoke operator is use it as a Factory Method, for example:

//          v--- call the invoke(String) operator 
val data1 = Data("1")

//            v--- call the invoke() operator 
val default = Data()

//          v-- call the constructor
val data2 = Data(2)

This is because the companion object is a special object in Kotlin. Indeed, the code Data("1") above is translated to the code as below:

val factory:Data.Companion = Data

//                       v-- the invoke operator is used here
val data1:Data = factory.invoke("1")

class Data(val value: Int) {

    companion object {
        const val DEFAULT =-1
        //           v--- factory method
        operator fun invoke(value: String): Data = Data(value.toInt())

        //           v--- overloading invoke operator
        operator fun invoke(): Data = Data(DEFAULT)
    }
}

Yes, you can overload invoke. Here's an example:

class Greeter(val greeting: String) {
    operator fun invoke(target: String) = println("$greeting $target!")
}

val hello = Greeter("Hello")
hello("world")  // Prints "Hello world!"

In addition to what @holi-java said, overriding invoke is useful for any class where there is a clear action, optionally taking parameters. It's also great as an extension function to Java library classes with such a method.

For example, say you have the following Java class

public class ThingParser {
    public Thing parse(File file) {
        // Parse the file
    }
}

You can then define an extension on ThingParser from Kotlin like so:

operator fun ThingParser.invoke(file: File) = parse(file)

And use it like so

val parser = ThingParser()
val file = File("path/to/file")
val thing = parser(file)  // Calls ThingParser.invoke extension function