在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>
而不是第一个。
答案 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…
}
a
和b
是什么?他们还没有任何意义。他们只是在说“调用此函数时,必须传递这些值”。您希望函数的主体以某种方式引用它们。那是他们习惯的时候。
现在考虑一个通用函数:
fun <T, U> myFun(/* …use T and U… */) {
// …
}
T
和U
相同。这些也是参数- 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>
表示)。
我希望我的解释对您来说是清楚而有启发性的!