//定义泛型类 定义泛型函数 多泛型参数 泛型约束
// <>符号中放一个字母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
但实际会报错
解决方案 修改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")