> 文档中心 > kotlin 基础 接口 泛型 协变 逆变

kotlin 基础 接口 泛型 协变 逆变


kotlin 基础入门

第七章 kotlin 接口 泛型 协变 逆变


文章目录

  • kotlin 基础入门
  • 前言
    • 1、接口的定义
    • 2、抽象类
    • 3、定义泛型类
    • 4、泛型函数
    • 5、泛型变换
    • 6、泛型类型约束
    • 7、vararg 关键字(动态参数)
    • 8、[] 操作符
    • 9、out 协变 & in 逆变 的使用

前言

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


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//    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//    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    }}