参考链接

Kotlin官方文档

https://kotlinlang.org/docs/home.html

中文网站

https://www.kotlincn.net/docs/reference/properties.html

本系列为参考Kotlin中文文档

https://download.csdn.net/download/u011109881/21418027

整理的笔记

pdf也可以在这里下载

https://www.kotlincn.net/docs/kotlin-docs.pdf

部分示例来自bilibili 动脑学院的Kotlin 泛型的视频讲解

第二章 第九节 泛型

知识点

1 Kotlin中的泛型的基本用法

2 泛型函数

3 多泛型参数

4 泛型约束

5 泛型中的类型推断

6 Kotlin中的型变

7 协变demo

8 逆变demo

9 协变与逆变示例在Java中的写法

笔记

fun main() {// 1 Kotlin中的泛型的基本用法// 可以装下任何类型的Boxval box1 = MagicBox("aaa")println(box1.item)val box2: MagicBox<Dog> = MagicBox(Dog("xiaohei"))println(box2.item.name)val box3: MagicBox<Boy> = MagicBox(Boy("zhangsan", 15))println(box3.item.name + box3.item.age)// 2 泛型函数box2.avaliable = true// 如果fetch返回值不是空 则执行run方法体box2.fetch()?.run {println("returned data ${this.name}")}box2.avaliable = falseval data = box2.fetch()?.run {println("returned data ${this.name}")}println("data is $data")// 3 多泛型参数val box4: MagicBox<Boy> = MagicBox(Boy("zhangsan", 15))box4.avaliable = true// change 方法入参是Boy 返回类型是Man// 为什么入参是Boy subjectModFun(subject)中 subject就是Boy类型的val man: Man? = box4.change {Man(it.name, it.age.plus(10))}man?.run { println("${this.name},${this.age}") }// 4 泛型约束// val box6: MagicBox1<Dog1> = MagicBox1(Dog1("xiaohei"))// 报错 Dog不是Human1类型val box7: MagicBox1<Boy1> = MagicBox1(Boy1("xiaohei", 12))val box8: MagicBox1<Man1> = MagicBox1(Man1("xiaohei", 22))// 5 泛型中的类型推断// 类型参数可以推断出来,例如从构造函数的参数或者从其他途径,允许省略类型参数// 以下写法都是等价的val box9: MagicBox<Int> = MagicBox<Int>(1)val box10: MagicBox<Int> = MagicBox(1)val box11 = MagicBox(1)// // 1 具有类型 Int,所以编译器知道我们说的是 Box<Int>。// 6 Kotlin中的型变// 型变分为两种协变和逆变// 协变: 父类可以使用的地方子类也可以使用// 父类引用指向子类对象// 假设FastFood是Food的子类 如果有Box<FastFood>是Box<Food>的子类 即可以用Box<FastFood>替换Box<Food>// 我们称Box的泛型是协变的 (我们的例子中Box是Producer)// 逆变: 子类可以使用的地方父类也可以使用// 子类引用指向父类对象// 假设FoodStore是FastFoodStore的父类 如果有Box<FoodStore>是Box<FastFoodStore>的子类 即可以用Box<FoodStore>替换Box<FastFoodStore>// 我们称Box的泛型是逆变的 (我们的例子中Box是Consumer)// 7 协变demoval foodProducer1: Producer<Food> = FoodStore()foodProducer1.produce()val fastFoodProducer1: Producer<FastFood> = FastFoodStore()fastFoodProducer1.produce()val fastFoodProducer2: Producer<Food> = FastFoodStore()fastFoodProducer2.produce()// BurgerStore里面泛型为Burger 但是赋值的时候可以使用Producer<Burger> Producer<FastFood> Producer<Food>// 看起来Producer<Burger> Producer<FastFood> Producer<Food> 都可以指向 子类泛型Burger// 原因是Producer使用了out修饰符val burgerProducer1: Producer<Burger> = BurgerStore()burgerProducer1.produce()val burgerProducer2: Producer<FastFood> = BurgerStore()burgerProducer2.produce()val burgerProducer3: Producer<Food> = BurgerStore()burgerProducer3.produce()// 8 逆变demo// People里泛型为Food 然而 Consumer<Food> Consumer<FastFood> Consumer<Burger>等Food子类的泛型也能指向父类Food的泛型// 是因为Consumer使用了逆变 in 操作符val foodConsumer: Consumer<Food> = People()// 输出的都是 People eat FoodfoodConsumer.consume(Food())foodConsumer.consume(FastFood())foodConsumer.consume(Burger())val foodConsumer2: Consumer<FastFood> = People()foodConsumer2.consume(FastFood())foodConsumer2.consume(Burger())val foodConsumer3: Consumer<Burger> = People()foodConsumer3.consume(Burger())val fastFoodConsumer: Consumer<FastFood> = ModernPeople()fastFoodConsumer.consume(FastFood())fastFoodConsumer.consume(Burger())val fastFoodConsumer2: Consumer<Burger> = ModernPeople()fastFoodConsumer2.consume(Burger())val burgerConsumer: Consumer<Burger> = American()burgerConsumer.consume(Burger())// 9 协变与逆变示例在Java中的写法 参见 D0309GenericJava
}// out 协变 这里用在返回值上
interface Producer<out T> {fun produce(): T
}// in 逆变 这里用在输入参数上
interface Consumer<in T> {fun consume(item: T)
}// 不变
interface ProduceConsumer<T> {fun produce(): Tfun consume(item: T)
}open class Food
open class FastFood : Food()
class Burger : FastFood()// 生产者 结合协变 out使用 协变 用在参数
class FoodStore : Producer<Food> {override fun produce(): Food {println("produce food")return Food()}
}class FastFoodStore : Producer<FastFood> {override fun produce(): FastFood {println("produce fast food")return FastFood()}
}class BurgerStore : Producer<Burger> {override fun produce(): Burger {println("produce burger")return Burger()}
}// 消费者 结合in使用 逆变 用在返回值
class People : Consumer<Food> {override fun consume(item: Food) {println("People eat Food")}
}class ModernPeople : Consumer<FastFood> {override fun consume(item: FastFood) {println("ModernPeople eat FastFood")}
}class American : Consumer<Burger> {override fun consume(item: Burger) {println("American eat Burger")}
}// 4 泛型约束
// 利用继承约束泛型类型 和Java的extends有点像
abstract class Human1(val age: Int)
class Man1(val name: String, age: Int) : Human1(age)
class Boy1(val name: String, age: Int) : Human1(age)
class Dog1(val name: String)
class MagicBox1<T : Human1>(var item: T) {var avaliable: Boolean = falseprivate var subject: T = itemfun fetch(): T? {// 如果avaliable是true 返回 subject 否则返回nullreturn subject.takeIf { avaliable }}
}// 1 Kotlin中的泛型的基本用法
class Man(val name: String, val age: Int)
class Boy(val name: String, val age: Int)
class Dog(val name: String)
class MagicBox<T>(var item: T) {var avaliable: Boolean = falseprivate var subject: T = item// 2 泛型函数 返回一个T类型的对象fun fetch(): T? {// 如果avaliable是true 返回 subject 否则返回nullreturn subject.takeIf { avaliable }}// 3 多泛型参数// change方法 输入类型T 返回类型Rfun <R> change(subjectModFun: (T) -> R): R? {return subjectModFun(subject).takeIf { avaliable }/* 等价下面的内容return if (avaliable){subjectModFun(subject)}else{null}*/}
}class D0309Generic
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;public class D0309GenericJava {static void copyAll2(Collection<? extends Object> collection) {// Collection<String> 是 Collection<? extends Object>的子类}static void copyAll3(Collection<Object> collection) {// Collection<String> 不是 Collection<Object>的子类}static void copyAll4(Collection<? super String> collection) {// Collection<Object> 是 Collection<? super String>的子类}static void copyAll(Collection<Object> to, Collection<String> from) {to.addAll(from);// addAll的实际定义 :boolean addAll(Collection<? extends E> var1);// 而不是想象中的 boolean addAll(Collection<E> items);// 想象中的定义对于这种简单声明的 addAll 将不能编译:// 因为Collection<String> 不是 Collection<Object> 的子类型// 但实际上可以编译通过 是因为Collection<String> 是 Collection<? extends Object>的子类}public static void main(String[] args) {// 几种基本类型的子类父类关系List<String> strings = new ArrayList<>();List<Object> obj = new ArrayList<>();// obj = strings; List<Object> 不是 List<String> 的父类// strings = obj; List<String>不是 List<Object> 的子类copyAll(obj,strings);copyAll2(strings);//copyAll3(strings);// 编译报错copyAll4(obj);// Java协变的写法 父类对象指向子类引用// 协变: 父类可以使用的地方子类也可以使用// 父类引用指向子类对象Producer<? extends Food> foodStore = new FoodStore();foodStore.produce();Producer<? extends Food> fastFoodStore = new FastFoodStore();fastFoodStore.produce();Producer<? extends FastFood> fastFoodStore2 = new FastFoodStore();fastFoodStore2.produce();Producer<? extends Food> burgerStore1 = new BurgerStore();burgerStore1.produce();Producer<? extends FastFood> burgerStore2 = new BurgerStore();burgerStore2.produce();Producer<? extends Burger> burgerStore3 = new BurgerStore();burgerStore3.produce();// Java逆变的写法// 逆变: 子类可以使用的地方父类也可以使用// 子类引用指向父类对象Consumer<? super Food> foodConsumer = new People();foodConsumer.consume(new Food());foodConsumer.consume(new FastFood());foodConsumer.consume(new Burger());Consumer<? super FastFood> foodConsumer2 = new People();foodConsumer2.consume(new FastFood());foodConsumer2.consume(new Burger());Consumer<? super Burger> foodConsumer3 = new People();foodConsumer3.consume(new Burger());Consumer<? super FastFood> fastFoodConsumer = new ModernPeople();fastFoodConsumer.consume(new FastFood());fastFoodConsumer.consume(new Burger());Consumer<? super Burger> fastFoodConsumer2 = new ModernPeople();fastFoodConsumer2.consume(new Burger());Consumer<? super Burger> burgerConsumer = new American();burgerConsumer.consume(new Burger());}// 协变 这里用在返回值上interface Producer<T> {T produce();}// 逆变 这里用在输入参数上interface Consumer<T> {void consume(T food);}public static class Food {}public static class FastFood extends Food {}public static class Burger extends FastFood {}// 生产者 结合协变 out使用 协变 用在参数static class FoodStore implements Producer<Food> {@Overridepublic Food produce() {System.out.println("produce food");return new Food();}}static class FastFoodStore implements Producer<FastFood> {@Overridepublic FastFood produce() {System.out.println("produce fast food");return new FastFood();}}static class BurgerStore implements Producer<Burger> {@Overridepublic Burger produce() {System.out.println("produce burger");return new Burger();}}static class People implements Consumer<Food> {@Overridepublic void consume(Food food) {System.out.println("People eat Food");}}static class ModernPeople implements Consumer<FastFood> {@Overridepublic void consume(FastFood food) {System.out.println("ModernPeople eat FastFood");}}static class American implements Consumer<Burger> {@Overridepublic void consume(Burger food) {System.out.println("American eat Burger");}}
}

Kotlin学习笔记 第二章 类与对象 第九节 泛型相关推荐

  1. Kotlin学习笔记 第二章 类与对象 第一节类与继承(补)

    参考链接 Kotlin官方文档 Kotlin docs | Kotlin 本系列为参考Kotlin中文文档 kotlin官方文档2020版.pdf-其它文档类资源-CSDN下载 第二章 第一节 类与继 ...

  2. Kotlin学习笔记 第二章 类与对象 第十一节 枚举类 第八节密封类

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

  3. Kotlin学习笔记 第二章 类与对象 第五节 可见性 第六节 扩展

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

  4. Kotlin学习笔记 第二章 类与对象 第十四 十五节 委托 委托属性

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

  5. Kotlin学习笔记 第二章 类与对象 第七节 数据类

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

  6. Kotlin学习笔记 第二章 类与对象 第十二 十三节 对象表达式与对象声明 类型别名

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

  7. Kotlin学习笔记 第二章 类与对象 第三节接口 第四节 函数式接口

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

  8. Kotlin学习笔记 第二章 类与对象 第二节属性

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

  9. Kotlin学习笔记 第二章 类与对象 第十节 内部类嵌套类

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

最新文章

  1. 如何获得Oracle系统性能统计? Oracle大型数据库系统在AIXUNIX上的实战详解 集中讨论 14...
  2. 使用Maven打包你的应用——maven-jar-plugin maven-assembly-plugin maven-shade-plugin
  3. VC++动态链接库(DLL)编程(一)――理解库
  4. JavaWeb:上传下载文件
  5. [.NET开发] C#编程调用Cards.dll实现图形化发牌功能示例
  6. 双流棠湖中学怎么样_2020年双流中学和棠湖中学哪个好?
  7. [摘抄]MySQL数据库系统的常规管理介绍
  8. 使用Python进行汽车黑客攻击:泄露GPS和OBDIICAN总线数据
  9. 一个求矩阵鞍点(即行上最小的数 同时是列上最大的数)的C程序
  10. HIve map jion的原理、操作和使用场景
  11. 以非泛型方式调用泛型方法
  12. wince与android USB通信,WinCE全站仪如何与手机通过USB互传数据
  13. 百度网盘青春版未推出前,使用这个网盘高速下载工具
  14. Matlab画柱状图和饼状图以及横纵坐标设置,宽度设置等
  15. python-scrapy模拟登陆网站--登陆青果教务管理系统(一)
  16. 更多:Racket系统编程
  17. python爬虫爬取豆瓣电影为啥内容有缺失-Python爬虫之抓取豆瓣影评数据
  18. Wiki引擎mediawiki
  19. Qt开发——图片缩放简述
  20. 虚拟内存怎么设置最好_虚拟内存怎么设置到d盘

热门文章

  1. 用excel 2016连接mysql_excel导入mysql数据库方法(最新,2016年2月19日)
  2. python入门之装饰器
  3. Rwordseg和tmcn安装-2017.09.23
  4. 【转】C# HttpWebRequest提交数据方式
  5. Hibernate自动事务揪出的编码不规范
  6. 个人收藏的flex特效网址【经典中的极品】
  7. 浅谈基于软交换的下一代网络技术
  8. Oracle Warehouse Builder 自动化ETL处置处罚历程(1)
  9. Ubuntu20.04 命令行 修改IP地址
  10. C/C++ list链表的理解以及使用