一手遮天 Android - kotlin: 泛型

项目地址 https://github.com/webabcd/AndroidDemo
作者 webabcd

一手遮天 Android - kotlin: 泛型

示例如下:

/kotlin/Demo11.kt

/**
 * 本例用于演示泛型(泛型类,泛型接口,泛型方法,泛型约束,型变)
 */

package com.webabcd.androiddemo.kotlin

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.webabcd.androiddemo.R
import kotlinx.android.synthetic.main.activity_kotlin_helloworld.*

class Demo11 : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_kotlin_demo11)

        sample1() // 泛型类,泛型接口,泛型方法
        sample2() // 泛型约束
        sample3() // 型变
    }

    fun sample1() {
        // 调用泛型类
        var a: Class1<String> = Class1<String>("webabcd") // 写全代码的
        var b = Class1("webabcd") // 编译器自己做类型推断的
        appendMessage("${a.value}, ${b.value}") // webabcd, webabcd

        // 调用泛型方法
        var c: String = function1<String>("webabcd") // 写全代码的
        var d = function1("webabcd") // 编译器自己做类型推断的
        appendMessage("$c, $d") // webabcd, webabcd
    }
    // 泛型类(泛型接口也类似,我就不写了)
    fun<T> function1(value: T) : T {
        return value;
    }
    // 泛型方法
    class Class1<T>(t: T) {
        var value = t
    }



    fun sample2() {
        var a = Class2("webabcd");
        var b = Class3("wanglei");

        appendMessage(function2(a)) // a 是 Class2 类型,符合约束条件
        appendMessage(function2(b)) // b 是 Class3 类型,其继承自 Class2 所以符合约束条件

        appendMessage(function3(b)) // b 是 Class3 类型,其同时继承自 Class2 和 Interface1 所以符合约束条件
        // appendMessage(function3(a)) // a 是 Class2 类型,其没有继承自 Interface1 所以不符合约束条件,会在编译时报错
    }
    // 泛型只有一个约束条件的写法
    // 下例 T 必须是 Class2 或是 Class 2 的子类
    fun<T: Class2> function2(param: T): String {
        return param.name
    }
    // 泛型有一个约束条件或多个约束条件的写法
    // 下例 T 必须同时继承自 Class2 和 Interface1
    fun<T> function3(param: T): String  where T: Interface1, T: Class2  {
        return param.name
    }
    interface Interface1 {
        var name: String
    }
    open class Class2(var name: String) {

    }
    class Class3(name: String) : Class2(name), Interface1 {

    }



    // 型变的示例
    fun sample3() {

        // Class5 是 Class4 的子类,所以下面这个协变是正常的
        var x: Class4 = Class5()


        var a = Class6(Class5())
        // 虽然 Class5 是 Class4 的子类,但是 Class6<Class5> 却不是 Class6<Class4> 的子类,所以下面这句协变会编译报错
        // var b: Class6<Class4> = a


        var c = Class7(Class5())
        // 看一下 Class7 的 out 修饰符,有了它下面这句协变就正常了(没有 out 则编译报错)
        var d: Class7<Class4> = c


        var e = Class8(Class4())
        // 看一下 Class8 的 in 修饰符,有了它下面这句逆变就正常了(没有 in 则编译报错)
        var f: Class8<Class5> = e


        var g = Class6(Class5())
        // 如果不想在类的泛型定义中加 out 修饰符,又想协变怎么办呢
        // 那就像下面这样,在类型声明处加上 out 修饰符
        var h: Class6<out Class4> = g


        var i = Class6(Class5())
        // 如果你也不确定基类是啥,怎么办
        // 当然可以用 out Any? 是没问题的,另外也可以用 *
        // 但是这样协变后,你就不能把泛型参数传入对象的任何方法了(即泛型参数可读不可写),会编译报错(因为这样协变后就不知道泛型的参数类型了)
        var j: Class6<out Any?> = i
        var k: Class6<*> = i
    }
    class Class6<T>(a: T) { }
    class Class7<out T>(a: T) { }
    class Class8<in T>(a: T) { }
    open class Class4() { }
    class Class5() : Class4() { }



    fun appendMessage(message: String) {
        textView1.append(message)
        textView1.append("\n")
    }
}

/layout/activity_kotlin_demo11.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

项目地址 https://github.com/webabcd/AndroidDemo
作者 webabcd

posted @ 2021-05-31 12:15  webabcd  阅读(90)  评论(0编辑  收藏  举报