【问题标题】:Extension function on a generic type泛型类型的扩展函数
【发布时间】:2019-02-17 19:40:55
【问题描述】:

我是 Kotlin 的新手,我正在尝试了解类型别名和函数。
我有以下示例:

interface EmptyInterface
typealias GenericCase<T> = T.(EmptyInterface) -> T

val myFunctionVariable: GenericCase<String> = {
    _ -> "Hello world!"
}

到目前为止,我的理解是,我扩展了 T 定义的函数,该函数接受 EmptyInterface 作为参数并返回 T。 所以myFunctionVariable 是一个应该通过EmptyInterface 调用的函数

但是下面的代码不能编译

class a: EmptyInterface
println("${myFunctionVariable(a())}")  

我需要传递一个String 作为第一个参数:

class a: EmptyInterface
println("${myFunctionVariable("",a())}")

为什么需要字符串作为第一个参数? T.(EmptyInterface) -&gt; T 在这种情况下是 String.(EmptyInterface) -&gt; String 只有 1 个参数。 有人可以解释一下吗?

【问题讨论】:

    标签: kotlin kotlin-extension kotlin-function-type


    【解决方案1】:

    T.(EmptyInterface) -&gt; T 类型中的T. 表示该函数是T 上的扩展函数。所以调用这个函数的常规方法是获取一个T 实例,并在该实例上调用它,就好像它是一个成员函数一样。在您的示例中,您选择T 作为String,您必须在String 实例上调用该函数:

    "foo".myFunctionVariable(a())
    

    您使用的语法是调用此扩展的另一种方法,将接收器作为函数的第一个参数传递(在字节码级别,它实际上是):

    myFunctionVariable("foo", a())
    

    但是,如果您希望使用这种语法来使用您的函数,最好将其声明为接受两个参数,因为这种扩展函数的调用可能非常出乎意料。

    (在this answer 中,有一些关于如何在作为类型扩展的函数和将其作为第一个参数的函数之间来回切换的更多信息。

    【讨论】:

    • 但是typealias 是如何在这里发挥作用的呢?我认为通过声明类型别名的方式,我基本上正在做你提到的事情,即"foo".myFunctionVariable(a())
    • typalias 在这种情况下并没有太大区别,它没有引入全新的类型,它只是使您的代码更具可读性的简写。 GenericCase&lt;String&gt; 类型的变量具有别名所代表的类型,因此在本例中为 String.(EmptyInterface) -&gt; String。该类型是一个扩展String的函数,接受EmptyInterface参数,并返回String
    【解决方案2】:

    T.(EmptyInterface) -&gt; T 类型中,第一个T接收者:函数被调用的实例,在函数定义中成为this。 (类似于扩展函数。)

    实际上,接收器成为函数的隐藏第一个参数;正如您所发现的,如果您尝试直接调用该函数,则需要明确给出它。

    它的语言规范是here;一些other answers 也可能有帮助。

    【讨论】:

    • 但我使用的是typealias。为什么它就像我通过this 调用它一样?
    • 接收者与参数类型或返回类型一样是类型的一部分。所以 typealias 意味着你的 myFunctionVariable 有一个值,它是一个接收接收者的函数,并且在调用函数时需要以某种方式指定接收者。
    • 但是定义的函数是(EmptyInterface) -&gt; T。在这种情况下,这扩展了String。所以我可以做"".myFunctionVariable(a())。我坚持的地方是我没有将它定义为{ _,_ -&gt; "Hello world!"}
    • 接收者是一个隐式参数。它不像其他形式参数那样传递(所以你不要将它包含在参数列表中);相反,它在函数中作为this 的值传递。
    • 好的,我知道了隐含的thistypealias 不是该类型的别名吗?那么为什么在这种情况下this 变得明确呢?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多