kotlin 接口 泛型 协变 逆变

举报
半身风雪 发表于 2022/06/24 11:56:44 2022/06/24
【摘要】 @[TOC](kotlin 接口 泛型 协变 逆变) 前言使用纯代码 加 注释的方式,可以更快的理解源码如果你喜欢,请点个赞,后期会不断的深入讲解 1、接口的定义// 接口里面的所有的成员 和 接口本身,都是 public open 的// 接口不能有主构造// 实现类不仅仅要重写接口的函数,也要重写接口的成员 val mouse = Mouse() print...

@[TOC](kotlin 接口 泛型 协变 逆变)


前言

使用纯代码 加 注释的方式,可以更快的理解源码
如果你喜欢,请点个赞,后期会不断的深入讲解


1、接口的定义

//    接口里面的所有的成员 和 接口本身,都是 public open 的
//    接口不能有主构造
//    实现类不仅仅要重写接口的函数,也要重写接口的成员

    val mouse = Mouse()
    println(mouse.insertUBS())

    val keyBoard = KeyBoard()

//    可以任意的更改set 的值。
    keyBoard.usbInsertDevice = "王五"
    println(keyBoard.insertUBS())


interface IUSB {

    var usbVersionInfo: String   //USB 相关版本的信息
    var usbInsertDevice: String   //USB 插入的设备信息

    fun insertUBS(): String             // 插入UBS 的实现
}

// 鼠标USB 的实现
class Mouse(override var usbVersionInfo: String = "USB 6.9",
            override var usbInsertDevice: String = "鼠标插入了USB 接口") : IUSB {
    override fun insertUBS(): String {

        return "版本号为:$usbVersionInfo 的 $usbInsertDevice"
    }

}

// 键盘 USB 的实现
class KeyBoard : IUSB {

//    下面的set ,get 都会持有 field,如果没有给 usbVersionInfo 赋值,意味着 field 是没法让set/get 持有的
    override var usbVersionInfo: String = "高级键盘"
        get() = field
        set(value) {
            field = value
        }
    override var usbInsertDevice: String = "接入了USB"
        get() {
            println("你可以get 到 $field 的数据出去")
            return field
        }
        set(value) {
            field = value
            println("你set 进来了 $field 的值")
        }

    override fun insertUBS(): String {

        return "键盘的的内容输出是: $usbVersionInfo , $usbInsertDevice"
    }

}


2、抽象类

//    在kotlin 中,抽象类和Java 完全是一样的
    val mainActivity = MainActivity()
    mainActivity.show()

abstract class BaseActivity{
    fun onCreate(){
        setContentView(getLayoutID())
        initView()
        initData()
    }

    private fun setContentView(layoutID: Int) = println("加载$layoutID 布局中")

    abstract fun getLayoutID(): Int
    abstract fun initView()
    abstract fun initData()


    fun show(){
        onCreate()
    }


}

class MainActivity() : BaseActivity(){
    override fun getLayoutID(): Int {
        return 662
    }

    override fun initView() {
        return println("加载view")
    }

    override fun initData() {
        return println("加载数据")
    }

}

3、定义泛型类

//  在kotlin 中,泛型的定义,和Java 也没有什么太大区别
    Person("张三").show()
    Person(11).show()
    Person(22.3f).show()
    Person('男').show()

class Person<T> (private val obj: T){
    fun show() = println("我是泛型,你传啥,我都能输出 $obj")
}

4、泛型函数

    println(Person(true, "张三").show())
    println(Person(true, 11).show())
    println(Person(false, 33.3f).show())
    println(Person(false, '男').show())


// 泛型函数, 使用Boolean 来控制对象是否返回, 运用takeIf (为true就返回对象本身,false 就返回null)
class Person<T> (private val isR: Boolean, private val obj: T){
    fun show() = obj.takeIf { isR }
}

5、泛型变换

    val person = Person(true, "学生")

    person.map {
        println(it)
    }


class Person<T>(val isMap: Boolean = false, val inputType: T){
//    模仿RxJava T 是要变换的输入类型, R是变换后输出的类型
//    map 返回的类型有可能是R,也有可能是null
    inline fun <R> map(mapAction: (T) -> R) = mapAction(inputType).takeIf { isMap }
}

6、泛型类型约束


    val person = Person("tiger", 88)
    val study = Study("tiger", 18)

    println(TextGeneric(person, true).show())

    println(TextGeneric(study).show())



open class MyAnyClass(name: String) {    // 顶级父类

}

open class Person(name: String, age: Int) : MyAnyClass(name) {

}

class Study(name: String, age: Int) : Person(name, age) {

}

class Teacher(name: String, age: Int) : Person(name, age) {

}

class TextGeneric<T : Person>(private val inputTypeInfo: T, private val isR: Boolean = false) {

//    万能的返回器
    fun show() = inputTypeInfo.takeIf { isR }
}

7、vararg 关键字(动态参数)

    val p = Person("tiger", '男', 333, 32.5f, isR = true)
    println(p.showObject(1))
    println(p.showObject(2))
    println(p.showObject(3))

    p.mapObject(1){
        println("转换成String $it")
    }

class Person<T>(vararg objects: T, val isR: Boolean) {
    // objetArray: Array<T>
//    out 指定 T 只能读取,不能修改
    private val objectArray: Array<out T> = objects

    // showObject(index)
    fun showObject(index: Int) = objectArray[index].takeIf { isR }

    // mapObject(index 变换成 Lambda) objectArray[index]
    fun <O> mapObject(index: Int, mapAction: (T) -> O) {
        mapAction(objectArray[index])
    }

}

8、[] 操作符

    val p = Person("tiger", '男', 333, 32.5f, isR = true)
    println(p[1])
    println(p[2])
    println(p[3])


class Person<T>(vararg objects: T, val isR: Boolean) {
    // objetArray: Array<T>
//    out 指定 T 只能读取,不能修改
    private val objectArray: Array<out T> = objects

    // operator 运算符重载,在使用的时候,可以直接使用 [] 调用就可以了
   operator fun get(index: Int) = objectArray[index].takeIf { isR }


}

9、out 协变 & in 逆变 的使用

out 协变:父类 = 子类
in 逆变: 子类 = 父类

    val setClass = SetClass<String>()
    println(setClass.setItem("tiger"))

    val getClass = GetClass("张三")
    println(getClass.getItem())

//  in T 逆变 【 in T SetClass 只能修改,更改,不能被外界获取 】
class SetClass<in T>{
    fun setItem(item: T): String {
        return "你要设置的数据是:$item"
    }

}

//  out T 协变 【 out T GetClass 可以被获取,读取,不能被修改】
class GetClass<out T>(_item: T) {

    private val item: T = _item
    fun getItem(): T {
        return item
    }
}

总结

🤩
🎉 原创不易,还希望各位大佬支持一下 \textcolor{blue}{原创不易,还希望各位大佬支持一下}

👍 点赞,你的认可是我创作的动力! \textcolor{green}{点赞,你的认可是我创作的动力!}

🌟 收藏,你的青睐是我努力的方向! \textcolor{green}{收藏,你的青睐是我努力的方向!}

✏️ 评论,你的意见是我进步的财富! \textcolor{green}{评论,你的意见是我进步的财富!}

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。