【问题标题】:Invoke Operator & Operator Overloading in Kotlin在 Kotlin 中调用运算符和运算符重载
【发布时间】:2017-12-23 17:29:21
【问题描述】:

我了解了 Invoke 运算符,

a() 等价于a.invoke()

关于 Invoke 运算符还有什么,请解释一下。另外,我没有得到任何 Invoke 运算符重载的示例。

Invoke 运算符重载是可能的吗?如果可能的话,任何人都可以用一个例子来解释 Invoke 运算符重载。我对此一无所知。

提前致谢。

【问题讨论】:

    标签: operator-overloading kotlin


    【解决方案1】:

    是的,您可以重载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
    

    【讨论】:

    • 您能否更详细地解释第二个示例。
    • 当然,如果您能告诉我您希望详细说明的内容。有没有什么特别没有意义的部分?
    • 把第二个程序详细解释一下。
    • Parser.invoke(file: File) 或 ThingParser.invoke(file: File)
    • invoke 只是一个运算符函数。您可以将其实现为扩展函数、高阶函数,或者两者都不是,或两者兼而有之。在这种情况下,它是一个扩展函数,而不是一个高阶函数。
    【解决方案2】:

    使用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)
        }
    }
    

    【讨论】:

    • @AvijitKarmakar 一点也不。这是我的荣幸,:)
    • 为什么不使用命名的默认值作为参数?
    • @Antek 嘿嘿,这只是介绍工厂方法的一个例子。如果您将Data 设置为接口,您会知道为什么?
    • @holi-java 嗯,不是真的 - 您也可以使用接口的默认值。你能进一步解释一下吗?
    【解决方案3】:

    如果你有一些 Python 背景,

    您可以将 Kotlin 中的 invoke 视为 Python 中的 __call__

    通过使用它,您可以“调用”您的对象,就像它是一个函数一样。

    一个区别是:你可以重载invoke,但是在Python中并没有官方的方法来重载方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-24
      • 1970-01-01
      • 2012-11-26
      • 2016-02-19
      • 2015-03-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多