Kotlin之泛型

2023-07-06  本文已影响0人  Deck方

一、泛型类

class MagicBox<T>(item:T){
    private var subject:T =item
}

class Boy(val name:String,val age:Int)
class Dog(val weight:Float)

fun  main(){
    var magicBoxBoy:MagicBox<Boy> = MagicBox(Boy("Jack", 28))
    var magicBoxDog:MagicBox<Dog> = MagicBox(Dog(20f))
}

二、泛型函数

class MagicBox<T>(item: T) {

    var available = false
    private var subject: T = item

    fun fetch(): T? {
        return subject.takeIf {
            available
        }
    }

}

class Boy(val name: String, val age: Int)
class Dog(val weight: Float)

fun main() {
    var magicBoxBoy: MagicBox<Boy> = MagicBox(Boy("Jack", 28))
    var magicBoxDog: MagicBox<Dog> = MagicBox(Dog(20f ))
    magicBoxBoy.available=true
     magicBoxBoy.fetch()?.run {
         println("$name")
     }
} 

三、多泛型参数

class MagicBox<T>(item: T) {
var available = false
    private var subject: T = item

    fun <R> fetch(subjectModFunction: (T) -> R): R? {
        return subjectModFunction(subject).takeIf { available }
    }
}

四、泛型类型的约束

声明T类型是Human的子类

class MagicBox<T:Human>(item: T) {

    var available = false
    private var subject: T = item

    fun <R> fetch(subjectModFunction: (T) -> R): R? {
        return subjectModFunction(subject).takeIf { available }
    }
}

open class Human(val age: Int)
class Boy(val name: String, age: Int) : Human(age)
class Man(val name: String, age: Int) : Human(age)
class Dog(val weight: Float)

fun main() {
    var magicBoxBoy: MagicBox<Boy> = MagicBox(Boy("Jack", 28))
//    var magicBoxDog: MagicBox<Dog> = MagicBox(Dog( 20))
}

五、out(协变)和in(逆变)

1.out(协变),如果泛型类只将泛型类型作为函数的返回(输出),那么使用out,可以称之为生产类/接口,因为它主要是用来生产(produce)指定的泛型对象。

interface Production<out T> {
    fun product(): T
}

2.in(逆变),如果泛型类只将泛型类型作为函数的入参(输入),那么使用in,可以称之为消费者类/接口,因为它主要是用来消费(consume)指定的泛型对象。

interface Consumer<in T> {
    fun consume(item: T)
}

3.(不变)如果泛型类既将泛型类型作为函数参数,又将泛型类型作为函数的输出,那么既不用out也不用in

4.父类泛型对象可以赋值给子类泛型对象,使用in;子类泛型对象可以赋值给父类泛型对象,使用out

interface ProductionConsumer<T>{
    fun product():T
    fun consume(item:T)
}
interface Production<out T> {
    fun product(): T
}
open class Food()
open class FastFood : Food()
class Hamburger : FastFood()
class FoodStore:Production<Food>{
    override fun product(): Food {
        return Food()
    }
}

class FastFoodStore :Production<FastFood>{
    override fun product(): FastFood {
        return FastFood()
    }
}
class HamburgerStore:Production<Hamburger>{
    override fun product(): Hamburger {
        return Hamburger()
    }
}




class EveryBody:Consumer<Food>{
    override fun consume(item: Food) {
        println("eat food")
    }
}

class ModernPeople:Consumer<FastFood>{
    override fun consume(item: FastFood) {
        println("eat fastFood")
    }
}

class American:Consumer<Hamburger>{
    override fun consume(item: Hamburger) {
        println("eat hamburger")
    }
}
fun main() {

   val food: Production<Food> = FoodStore()
    //变量的类型声明中使用了父类类型,这java中这样赋值会有编译错误,但是kotlin中通过out实现了
//子类泛型对象可以赋值给父类泛型对象,使用out
   val fastFood: Production<Food> = FastFoodStore()

//父类泛型对象可以赋值给子类泛型对象,使用in
    val consumer :Consumer<Hamburger> = EveryBody()
}

六、reified

class MagicBox<T : Human>(item: T) {
//    fun <T> randomOrBackup(backup: () -> T): T {
//        val list = listOf(Boy("Jack", 28), Man("Bob", 24))
//        val random = list.shuffled().first()
//        return if (random is T) {
//            random
//        } else {
//            backup()
//        }
//    }

//reified 配合inline关键字
   inline fun <reified T> randomOrBackup(backup: () -> T): T {
        val list = listOf(Boy("Jack", 28), Man("Bob", 24))
        val random = list.shuffled().first()
        return if (random is T) {
            random
        } else {
            backup()
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读