IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Kotlin学习笔记 第二章 类与对象 第九节 泛型 -> 正文阅读

[移动开发]Kotlin学习笔记 第二章 类与对象 第九节 泛型

参考链接

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中的泛型的基本用法
    // 可以装下任何类型的Box
    val 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 = false
    val 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 协变demo
    val 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 Food
    foodConsumer.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(): T
    fun 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 = false
    private var subject: T = item
    fun fetch(): T? {
        // 如果avaliable是true 返回 subject 否则返回null
        return 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 = false
    private var subject: T = item

    // 2 泛型函数 返回一个T类型的对象
    fun fetch(): T? {
        // 如果avaliable是true 返回 subject 否则返回null
        return subject.takeIf { avaliable }
    }

    // 3 多泛型参数
    // change方法 输入类型T 返回类型R
    fun <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> {
        @Override
        public Food produce() {
            System.out.println("produce food");
            return new Food();
        }
    }

    static class FastFoodStore implements Producer<FastFood> {
        @Override
        public FastFood produce() {
            System.out.println("produce fast food");
            return new FastFood();
        }
    }

    static class BurgerStore implements Producer<Burger> {
        @Override
        public Burger produce() {
            System.out.println("produce burger");
            return new Burger();
        }
    }

    static class People implements Consumer<Food> {
        @Override
        public void consume(Food food) {
            System.out.println("People eat Food");
        }
    }

    static class ModernPeople implements Consumer<FastFood> {
        @Override
        public void consume(FastFood food) {
            System.out.println("ModernPeople eat FastFood");
        }
    }

    static class American implements Consumer<Burger> {
        @Override
        public void consume(Burger food) {
            System.out.println("American eat Burger");
        }
    }
}

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-09-02 11:30:10  更:2021-09-02 11:31:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:38:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码