Kotlin语法总结-泛型的使用
Posted LQS_Android
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin语法总结-泛型的使用相关的知识,希望对你有一定的参考价值。
怎样声明一个函数来判断两个参数是否相等呢?如果参数是Int类型,则函数声明如下:
private fun isEqualsInt(a: Int, b: Int): Boolean {
return (a == b)
}
这个函数参数列表是两个Int类型,它只能比较两个Int类型参数是否相等。如果想比较两个Double类型是否相等,可以修改上面声明的函数如下:
private fun isEqualsDouble(a: Double, b: Double): Boolean {
return (a == b)
}
这个函数参数列表是两个Double类型,它只能比较两个Double类型参数是否相等。如果想比较两个String类型是否相等,可以修改上面声明的函数如下:
private fun isEqualsString(a: String, b: String): Boolean {
return (a == b)
}
以上分别对3种类型的两个参数进行了比较,声明了类似的3个函数。
那么是否可以声明一个函数使之能够比较3种类型呢?
合并代码:
private fun <T> isEquals(a: T, b: T): Boolean {
return (a == b)
}
在函数名isEquals前面添加<T>这就是泛型函数了,<T>是声明类型参数,T是类型参数,函数中参数类型也被声明为T,在调用函数时T会用实际的类型替代。
泛型中类型参数,可以是任何大写或小写的英文字母,一般情况下人们习惯于使用字母T、E、K和U等大写英文字母。
fun main(args: Array<String>) {
println(isEquals(1, 5))
println(isEquals(1.0, 5.0))
}
多类型参数
fun <T, U> addRectangle(a: T, b: U): Boolean {...}
类型参数不仅可以声明函数参数类型,还可以声明函数的返回类型,示例代码如下:
fun <T, U> rectangleEquals(a: T, b: U): U {...}
泛型约束
private fun <T : Number> isEquals(a: T, b: T): Boolean { ①
return (a == b)
}
fun main(args: Array<String>) {
println(isEquals(1, 5)) //false ②
println(isEquals(1.0, 1.0)) //true ③
}
上述代码是声明泛型函数,其中<T : Number>是带有约束的类型参数。
如果函数泛型限定声明为 <T : Number>,则函数只能比较Number类型的参数,不能比较String等其他数据类型,为此也可以将类型参数限定为Comparable<T>接口类型,所有可比较的对象都实现Comparable<T>接口,Comparable<T>本身也是泛型类型。
fun <T : Comparable<T>> isEquals(a: T, b: T): Boolean {
return (a == b)
}
fun main(args: Array<String>) {
println(isEquals(1, 5)) //false
println(isEquals(1.0, 1.0)) //true
println(isEquals("a", "a")) //true ①
val d1 = Date()
val d2 = Date()
println(isEquals(d1, d2)) //true ②
}
可空类型参数和非空类型参数
println(isEquals(null, 5)) //false
所有没有泛型约束的类型参数,事实上也是有限定类型的,只不过是Any?,Any?可以任何可空类型的根类,也兼容非空类型。
private fun <T : Any> isEquals(a: T, b: T): Boolean { ①
return (a == b)
}
fun main(args: Array<String>) {
println(isEquals(null, 5)) //编译错误 ②
println(isEquals(1.0, null)) //编译错误 ③
}
泛型属性
val <T> ArrayList<T>.first: T? //获得第一个元素 ①
get() = if (this.size > 1) this[0] else null
val <T> ArrayList<T>.second: T? //获得第二个元素 ②
get() = if (this.size > 2) this[1] else null
fun main(args: Array<String>) {
val array1 = ArrayList<Int>()//等同于arrayListOf<Int>() ③
println(array1.first) //null
println(array1.second) //null
val array2 = arrayListOf ("A", "B", "C", "D") ④
println(array2.first) //A
println(array2.second) //B
}
上述代码第①行和第②行是声明ArrayList集合的扩展属性first和second,其中使用了泛型。集合中的元素类型采用类型参数T表示,返回类型是T?表示可能有返回空值的情况。
代码第③行是实例化,Int类型的ArrayList集合,使用ArrayList构造函数创建一个空元素的集合对象。也可以使用arrayListOf<Int>()函数创建集合对象。代码是④行是创建String类型ArrayList集合对象,这里使用arrayListOf<String>("A", "B", "C", "D")函数创建并初始化该集合。
泛型类
/**
* 自定义的泛型类
*/
class Queue<T> {
// 声明保存队列元素集合items
private val items: MutableList<T>
// init代码块初始化是集合items
init {
this.items = ArrayList()
}
/**
* 入队函数
*
* @param item 参数需要入队的元素
*/
fun queue(item: T) {
this.items.add(item)
}
/**
* 出队函数
* @return 返回出队元素
*/
fun dequeue(): T? {
return if (items.isEmpty()) {
null
} else {
this.items.removeAt(0)
}
}
override fun toString(): String {
return items.toString()
}
}
泛型接口:
/**
* 自定义的泛型队列集合
*/
interface IQueue<T> { ①
/**
* 入队函数
*
* @param item 参数需要入队的元素
*/
fun queue(item: T) ②
/**
* 出队函数
*
* @return 返回出队元素
*/
fun dequeue(): T? ③
}
实现接口IQueue<T>具体方式有很多,可以是List(列表结构)、Set(集结构)或Hash(散列结构)等多种不同方式,下面是一个基于List实现方式,代码如下:
/**
* 自定义的泛型队列集合
*/
class ListQueue<T> : IQueue<T> {
// 声明保存队列元素集合items
private val items: MutableList<T>
// init代码块初始化是集合items
init {
this.items = ArrayList()
}
/**
* 入队函数
*
* @param item
* 参数需要入队的元素
*/
override fun queue(item: T) {
this.items.add(item)
}
/**
* 出队函数
*
* @return 返回出队元素
*/
override fun dequeue(): T? {
return if (items.isEmpty()) {
null
} else {
this.items.removeAt(0)
}
}
override fun toString(): String {
return items.toString()
}
}
以上是关于Kotlin语法总结-泛型的使用的主要内容,如果未能解决你的问题,请参考以下文章