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