摘要:泛型对于有一定Java编程经验的同学,并不是什么陌生的东西,它允许我们在不指定具体类型的情况下,定义任何一个变量。这样我们写的代码会更具有灵活性和扩展性。
1. 泛型
泛型有泛型类和泛型方法两种定义方式。它们的语法结构都是,当然使用大些字母T只是我们使用泛型的潜规则,我们可以任意的使用其它字母甚至单词。
泛型类:
class MyClass<T> {
fun method(param:T):T{
return param
}
}
泛型方法:
class MyClass1 {
fun <T>method(param:T):T{
return param
}
}
我们可以以这样的姿势来使用泛型:
fun main() {
val myClass = MyClass<Int>()
myClass.method(123)
val myClass1 = MyClass1()
myClass1.method<String>("abc")
}
我们可以看到myClass1.method(“abc”)指定了String类型的泛型,其实由于Kotlin出色的类推导机制,此处我们可以不写泛型,Kotlin也能够知道我们的泛型是String,所以下面的代码也是可以正常运行的:
fun main() {
val myClass1 = MyClass1()
myClass1.method("abc")
}
和Java类似,Kotlin也允许我们对泛型的类型进行约束,如果你不想将泛型指定为任意类型,而想约束它为Number类型的话,我们可以这么写,这样我们就不可以在使用时将泛型指定为String了,代码如下:
class MyClass2 {
fun <T:Number>method(param:T):T{
return param
}
}
另外,在默认情况下,所有的泛型都可以指定成空类型,因为不手动指定上界的时候,泛型的默认上界是Any?,如果我们不想让泛型的类型为空,我们只需将上界指定为Any就可以了。那么Any又是什么呢?请看本文目录1.1Any。
接下来我们回忆下上篇文章中的内容,我们是不是写过一个高阶函数myApply呢:
fun StringBuilder.myApply(block:StringBuilder.() -> Unit):StringBuilder{
block()
return this
}
但是这个myApply只能作用在StringBuilder,如果我们想实现一个和apply完全一样的功能怎么办呢,其实用到我们所学习的泛型就可以,我们只需要用将myApply函数定义为泛型函数就可以了。我们可以这么写:
fun <T> T.myApply(block:T.() -> Unit) : T{
block
return this
}
然后我们就可以像调用apply一样的调用myApply了:
fun main() {
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
val result = StringBuilder().myApply {
for (fruit in list){
append(fruit).append(" ")
}
}
println("result is $result")
}
//result is Apple Banana Orange Pear Grape Watermelon
1.1 Any
Any是Kotlin中所有类的共同基类,相当于Java中的Object,而Any?则表示允许传入空值。