函数名称之前的通用类型<t>参数

时间:2019-02-26 07:33:17

标签: java generics kotlin

在Kotlin中,函数名称前<T>类型参数 的用途是什么?

示例:

fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
    val tmp = this[index1] 
    this[index1] = this[index2]
    this[index2] = tmp
}

请参阅上面的第一个<T>

我尝试遍历Kotlin docs关于泛型以及Java Generics的问题,但是它们大多只是触及第二个<T>而不是第一个。

5 个答案:

答案 0 :(得分:5)

它用于指示使用泛型,但未引用某些类型T

看看这个完全有效的示例

fun <String> MutableList<String>.swap(index1: Int, index2: Int)

现在可以在任何MutableList<*>上并且不仅在MutableList<String>上调用它。如果您不愿意在<String>关键字后写fun,那么kotlin怎么会知道您实际上是在引用泛型而不是kotlin.String

您显示的示例也是如此。 <>之后的fun只是引入了一个新的通用参数,否则kotlin会抱怨它不知道类型T

答案 1 :(得分:3)

(这是另一种方法。)

考虑正常的非泛型函数:

fun myFun(a: Int, b: String) {
    // …use a and b…
}

ab是什么?他们还没有任何意义。他们只是在说“调用此函数时,必须传递这些值”。您希望函数的主体以某种方式引用它们。那是他们习惯的时候。

现在考虑一个通用函数:

fun <T, U> myFun(/* …use T and U… */) {
    // …
}

TU相同。这些也是参数- type 参数。就像值参数一样,声明类型参数本身并不意味着任何东西,而是为调用函数时必须传递(显式或推断)的类型提供占位符。 (<…>声明还提供了一个位置来指定任何约束或差异,例如<T : Number><out T>。)通常,您以后会使用这些类型参数-在这种情况下,功能签名的其余部分。

答案 2 :(得分:2)

要添加到Lino的答案中,请想象此定义在类型参数声明之后具有不可见的花括号:

fun <T> \*{*\ MutableList<T>.swap(index1: Int, index2: Int) {...} \*}*\

所以正确lexically scoped。如果该<T>位于函数名之后,则您将失去此属性,使解析器复杂化,并且只会使代码对人类的可读性降低。

也很难记住将<T>放在扩展功能的名称之前,但将其放在成员功能的名称之后。够糟糕的,必须在课堂上完成!

Scala确实在方法名称后放置了[T],但这是因为它具有与扩展方法相对应的功能语法,它们的语法非常不同。 Scala 3将go for the complicated parser approach,可能是因为类似Kotlin的语法不适合任何其他语法。

答案 3 :(得分:0)

“ T”表示传递给函数的通用类型/类。您的问题是关于函数返回时的“ T”。因此,它假定根据您传递给函数的内容返回类型/类。

答案 4 :(得分:0)

您知道,第一个<T>向函数引入了泛型参数。第二个<T>MutableList<T>的一部分,是代码定义的extension function接收器:扩展函数定义为

乐趣[GenericTypeList] ReceiverType.FunctionName([ParametersList])[:ReturnType] {...}

如您在上面链接的官方文档中所见。 接收器类型是您将扩展功能添加到(扩展功能句法糖的类型,例如Java的static方法调用)。在您的示例中,您要向 generic MutableList<T>添加扩展功能,因此定义 receiver 时,您将提供一个泛型类型规范(需要 generic类型参数(由第一个<T>表示)。

我希望我的解释对您来说是清楚而有启发性的!