当前位置: 代码迷 >> 综合 >> kotlin--泛型
  详细解决方案

kotlin--泛型

热度:165   发布时间:2023-09-14 05:47:38.0

kotlin作为一种高级语言,也提供了泛型,它的泛型比Java更为灵活

一、泛型类

1.定义泛型类

定义泛型类和Java差不多

class Magic<T>(_item: T) {var subOject: T = _item
}data class Boy(var name: String, var age: Int)data class Dog(var age: Int)fun main() {println(Magic(Boy("danny", 15)).subOject)println(Magic(Dog(15)).subOject)
}

结果:
Boy(name=danny, age=15)
Dog(age=15)

二、泛型函数

1.泛型参数也可以用于函数
class Magic<T>(_item: T) {var subOject: T = _itemvar available: Boolean = falsefun getItem(): T? {//available为true,返回泛型类型对象subOjectreturn subOject.takeIf { available }}
}data class Boy(var name: String, var age: Int)fun main() {val magic = Magic(Boy("danny", 15))magic.available = trueprintln(magic.getItem())
}
2.多个泛型参数的函数
class Magic<T>(_item: T) {var subOject: T = _itemvar available: Boolean = falsefun <R> getItem(funp: (T) -> R): R? {//available为true,返回泛型类型对象Rreturn funp(subOject).takeIf { available }}
}data class Boy(var name: String, var age: Int)data class Man(var name: String, var age: Int)fun main() {val magic = Magic(Boy("danny", 15))magic.available = true//boy变成manval man = magic.getItem {Man(it.name, it.age.plus(10))}println(man)
}

三、泛型类型约束

1.如果想要对传递的泛型作约束,可以指定泛型的父类
//指定父类
class Magic<T : Human>(_item: T) {var subOject: T = _itemvar available: Boolean = false
}open class Human(var age: Int)
2.如果想要放入多个实例,使用vararg关键字
class Magic<T : Human>(vararg _items: T) {var subOject: Array<out T> = _itemsvar available: Boolean = false
}
3.使用[]操作符取值,也可以自己重载get函数
class Magic<T : Human>(vararg _items: T) {var subOject: Array<out T> = _itemsvar available: Boolean = falsefun <R> getItem(index: Int, funp: (T) -> R): R? {if (index > subOject.size - 1) return null//available为true,返回泛型类型对象Rreturn funp(subOject[index]).takeIf { available }}operator fun get(index: Int): T? {return subOject[index].takeIf { available }}
}//父类
open class Human(var age: Int)class Boy(var name: String, _age: Int) : Human(_age)class Man(var name: String, _age: Int) : Human(_age)fun main() {val magic = Magic(Boy("danny", 15))magic.available = true//boy变成manval man = magic.getItem(0) {Man(it.name, it.age.plus(10))}println("${man?.name} ${man?.age}")
}
4.out

out修饰泛型,表示该泛型对象可以赋值给父类

class Product<out T : Human>(val product: T) {fun getItem(): T? = product
}//父类
open class Human(var age: Int)class Boy(var name: String, _age: Int) : Human(_age)class Man(var name: String, _age: Int) : Human(_age)fun main() {//泛型是Human,传入的是Boy,Human的子类val boy: Product<Human> = Product(Boy("danny", 15))println(boy.getItem())
}

结果:
com.aruba.mykotlinapplication.Boy@3cd1a2f1

5.in

in修饰泛型,表示该泛型对象可以赋值给子类

class Consume<in T : Human>() {fun cousume(item: T) {println(item)}
}//父类
open class Human(var age: Int)open class Boy(var name: String, _age: Int) : Human(_age)class Man(_name: String, _age: Int) : Boy(_name, _age)fun main() {//泛型为Boy类型val man: Consume<Boy> = Consume()//传入的是Boy的父类Manman.cousume(Man("danny", 15))
}

结果:
com.aruba.mykotlinapplication.Man@3cd1a2f1

而Java中泛型只能使用对应的泛型,没有继承关系

6.reified

kotlin也不允许对泛型作类型检查,当我们想要知道泛型参数具体是哪个类型时,可以使用reified关键字修饰
reified必须和inline配合使用,原因是编译的时候,编译器就需要知道我们传入的类型,只不过代码写成了泛型而已

class Magic {inline fun <reified T : Human> getBoy(backUp: () -> T): T {//随机取一个val human = listOf(Boy("danny", 15),Man("jack", 25)).shuffled().first()println(human)//如果和backup函数返回参数的类型相同,直接返回return if (human is T) {human} else {//否则返回backup函数调用结果backUp()}}
}open class Human()class Boy(var name: String, var age: Int) : Human()class Man(var name: String, var age: Int) : Human()fun main() {val magic = Magic()println(magic.getBoy { Boy("danny", 15) })
}

随机到不是Boy型变量的结果:
com.aruba.mykotlinapplication.Man@3f99bd52
com.aruba.mykotlinapplication.Boy@4f023edb
随机到Boy型变量的结果:
com.aruba.mykotlinapplication.Boy@3f99bd52
com.aruba.mykotlinapplication.Boy@3f99bd52