kotlin基本语法<五> [泛型、扩展、函数式编程基础]

//定义泛型类 定义泛型函数 多泛型参数 泛型约束

 // <>符号中放一个字母T  T 是个代表item类型的占位符 然后将item赋值给同样是T类型的属性loot
    // T 可以是任意字母  不过约定俗成使用字母T 便于理解
    // T:Loot  约束性泛型 表示T只能是Loot类型或其子类
    class LootBox(item:T){
        var loot:T = item
        var open = false
        //定义泛型函数
        fun featch():T?{
            return loot.takeIf { open }
        }

        //多泛型参数  传入一个函数作为传参 该函数需要传入一个T类型的变量 返回一个R类型的值
        fun  fetch(lootFun:(T) -> R) : R?{
            return lootFun(loot).takeIf { open }
        }
    }

 var lootBox = LootBox(Loot())
vararg关键字 和 get 函数

上述例子创建LootBox 时只能传递一个Loot对象 使用vararg可传递多个对象

 class LootBox2(vararg item : T){
        var loot : Array = item
        fun get(index:Int): T {
            return loot.get(index)
        }
    }
    var lootBox2 = LootBox2(Loot() , Loot() , Loot())
    var lootIndex = lootBox2.get(0)
in 与 out

先看下面一段示例

 open class Fruit{

    }
    class WaterMellon : Fruit() {

    }

    class Barrel(var item:T){

    }

    var fruitBarrel = Barrel(Fruit())
    var waterMellonBarrel = Barrel(WaterMellon())
//    现在尝试给fruitBarrel 重新赋值
    fruitBarrel = waterMellonBarrel

按理说WaterMellon 是 Fruit 子类 把WaterMellon变量赋值给Fruit 是可以的
所以理论上 waterMellonBarrel应该可以赋值给fruitBarrel
但实际会报错


赋值报错.png

解决方案 修改Barrel 即可

T    -> out T
var -> val
 class Barrel(val item:T){

    }

原因 泛型参数可以扮演两种角色 生产者 和 消费者
生产者可读而不可写 消费者可写而不可读
out关键字表面 泛型参数将代表生产者角色,也就是说不能再用var定义item了 否则它不仅是生产者还可以是可写的消费者 让泛型参数代表生产者就告诉编译器现在item的值不会改变可以安全的把waterMellonBarrel 赋值给fruitBarrel 了

如果out改成in 的话
上面赋值代码就需要反转一下
只能是 waterMellonBarrel = fruitBarrel

 class Barrel(item:T){

    }

 waterMellonBarrel = fruitBarrel

扩展

//扩展可以在不直接修改类定义的情况下增加类的功能 扩展可以用于自定义类

// 扩展string函数
fun String.addEndFlag(count : Int = 1):String{
    return this + "。".repeat(count)
}

//扩展超类any函数
fun Any.print(){
    println(this)
}

// 扩展string属性
val String.numSize
get() = count{"aeiou".contains(it)}

fun main() {
    // 使用stirng扩展函数
    println("hello".addEndFlag())
    //使用超类扩展函数
    "hello".addEndFlag().print()

    //使用string扩展属性
    "hello".numSize.print()
}

函数式编程基础 函数类别 : 变换、过滤、合并

 // 变换器函数 常用的变换函数 map、flatMap
    val animals = listOf("zebra" , "giraffe","elephant")
    val babies = animals.map { animals -> "a baby $animals" }
        .map { baby -> "$baby , with the cutest little tail ever!" }
    println(animals)
    println(babies)

    // flatMap  合并两个函数
    var list = listOf(listOf(1,2,3), listOf(4,5,6))
    println(list)
    println(list.flatMap { it })

    //过滤函数 filter
    val numbers = listOf(1,2,3,4,5,6,7,8,9,10)
    // 过滤出偶数
    var filterNumber = numbers.filter { it % 2 == 0 }
    println(filterNumber)

    // 合并函数 zip fold
    val list1 = listOf(1,2,3)
    val list2 = listOf(4,5,6)
    // 返回的是一个包含键值对的新集合
    var list3 = list1.zip(list2)
    var list4 = list3.toMap()
    println(list3)
    println(list4)

    // 根据自定义的表达式计算合并结果 fold(0) 0代表初始值为0
    val foldedValue = listOf(1,2,3,4).fold(0){acc, i ->
        println("acc value: $acc")
        // 每个元素*10 然后依次累加
        acc + (i * 10 )
    }
    println("foldvalue = $foldedValue")

你可能感兴趣的:(kotlin基本语法<五> [泛型、扩展、函数式编程基础])