【发布时间】:2017-12-23 17:29:21
【问题描述】:
我了解了 Invoke 运算符,
a() 等价于a.invoke()
关于 Invoke 运算符还有什么,请解释一下。另外,我没有得到任何 Invoke 运算符重载的示例。
Invoke 运算符重载是可能的吗?如果可能的话,任何人都可以用一个例子来解释 Invoke 运算符重载。我对此一无所知。
提前致谢。
【问题讨论】:
标签: operator-overloading kotlin
我了解了 Invoke 运算符,
a() 等价于a.invoke()
关于 Invoke 运算符还有什么,请解释一下。另外,我没有得到任何 Invoke 运算符重载的示例。
Invoke 运算符重载是可能的吗?如果可能的话,任何人都可以用一个例子来解释 Invoke 运算符重载。我对此一无所知。
提前致谢。
【问题讨论】:
标签: operator-overloading kotlin
是的,您可以重载invoke。这是一个例子:
class Greeter(val greeting: String) {
operator fun invoke(target: String) = println("$greeting $target!")
}
val hello = Greeter("Hello")
hello("world") // Prints "Hello world!"
除了@holi-java 所说的之外,覆盖invoke 对于任何有明确操作的类都非常有用,可以选择获取参数。使用这种方法作为 Java 库类的扩展函数也很棒。
例如,假设您有以下 Java 类
public class ThingParser {
public Thing parse(File file) {
// Parse the file
}
}
然后,您可以像这样在 Kotlin 的 ThingParser 上定义扩展:
operator fun ThingParser.invoke(file: File) = parse(file)
然后像这样使用它
val parser = ThingParser()
val file = File("path/to/file")
val thing = parser(file) // Calls ThingParser.invoke extension function
【讨论】:
invoke 只是一个运算符函数。您可以将其实现为扩展函数、高阶函数,或者两者都不是,或两者兼而有之。在这种情况下,它是一个扩展函数,而不是一个高阶函数。
使用invoke 运算符的最常用方法是将其用作Factory Method,例如:
// 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)
这是因为companion object 是 Kotlin 中的一个特殊对象。确实,上面的代码Data("1")被翻译成如下代码:
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)
}
}
【讨论】:
Data 设置为接口,您会知道为什么?
如果你有一些 Python 背景,
您可以将 Kotlin 中的 invoke 视为 Python 中的 __call__。
通过使用它,您可以“调用”您的对象,就像它是一个函数一样。
一个区别是:你可以重载invoke,但是在Python中并没有官方的方法来重载方法。
【讨论】: