一手遮天 Android - kotlin: 类相关 1(基础)

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

一手遮天 Android - kotlin: 类相关 1(基础)

示例如下:

/kotlin/Demo7.kt

/**
 * 本例用于演示类的定义和使用(实例化对象,调用属性,调用方法,自定义 getter 和 setter,下标运算符 [] 的使用,扩展方法,扩展属性,静态属性,静态方法,嵌套类,内部类,局部类,匿名内部类,内联类,类型别名)
 */

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.*

// 类型别名,必须在顶层声明
typealias MyType = String

class Demo7 : AppCompatActivity() {

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

        sample1() // 实例化对象,调用属性,调用方法,自定义 getter 和 setter,下标运算符 [] 的使用,扩展方法,扩展属性
        sample2() // 静态属性,静态方法
        sample3() // 嵌套类,内部类,局部类
        sample4() // 匿名内部类
        sample5() // 内联类,类型别名
    }

    fun sample1() {
        // 实例化对象(不需要 new)
        var a: Demo7_Class = Demo7_Class("webabcd", "china")
        var b: Demo7_Class = Demo7_Class("webabcd", 40, "china")

        // 调用方法
        appendMessage(a.getInfo())
        appendMessage(b.getInfo())

        // 调用属性
        b.country = "中国"
        b.weight = 33
        appendMessage(b.getInfo())

        // 用于演示属性的自定义 getter 和 setter
        b.height = 2;
        appendMessage(b.getInfo())
        b.height = 20;
        appendMessage(b.getInfo())

        // 下标运算符 [] 的使用
        a[0] = "123"
        appendMessage(a[0])

        // 扩展方法和扩展属性
        appendMessage(a.myExtensionMethod()) // my extension method
        appendMessage(a.myExtensionProperty) // my extension property
        appendMessage(Demo7_Class.myCompanionExtensionMethod()) // my companion extension method
        appendMessage(Demo7_Class.myCompanionExtensionProperty) // my companion extension property
    }

    fun sample2() {
        // 静态属性(通过伴生对象实现,这种方式 Demo7_Class 可以有静态属性和实例属性)
        appendMessage(Demo7_Class.name)
        // 静态方法(通过伴生对象实现,这种方式 Demo7_Class 可以有静态方法和实例方法)
        appendMessage(Demo7_Class.hello("webabcd"))

        // 静态属性(通过 object 实现,这种方式 MyStatic 只可以有静态属性,不可以有实例属性)
        appendMessage(MyStatic.name)
        // 静态方法(通过 object 实现,这种方式 MyStatic 只可以有静态方法,不可以有实例方法)
        appendMessage(MyStatic.hello("webabcd"))
    }

    fun sample3() {
        // 嵌套类的使用
        var a: NestedClass = NestedClass("wanglei")
        appendMessage(a.hello())

        // 内部类的使用
        var b: InnerClass = InnerClass("wanglei")
        appendMessage(b.hello())

        // 定义一个局部类,即方法中的类(可以访问外部类的成员)
        class PartClass(name: String) {
            var name = ""
            init {
                this.name = name
            }
            fun hello(): String {
                // 可以访问外部类的成员
                this@Demo7.appendMessage("我是局部类")
                return "hello: $name"
            }
        }

        // 局部类的使用
        var c: PartClass = PartClass("wanglei")
        appendMessage(c.hello())
    }

    fun sample4() {
        // 通过 object 可以实现匿名内部类
        val a = object {
            val name = "webabcd"
            override fun toString() = "name: $name"
        }
        appendMessage("${a.name}, ${a.toString()}") // webabcd, name: webabcd

        var b: MyView = MyView()
        // 这里的 object 就是一个匿名内部类,其实现了 OnClickListener 接口
        b.setOnClickListener(object: OnClickListener {
            override fun onClick(message: String) {
                appendMessage(message)
            }
        })
        b.testListener()
    }
    // 用于演示匿名内部类
    class MyView {
        private lateinit var listener : OnClickListener
        fun setOnClickListener(listener: OnClickListener) {
            this.listener = listener
        }
        fun testListener(){
            if (this.listener != null)
                listener.onClick("xxx")
        }
    }
    interface OnClickListener {
        fun onClick(message: String)
    }

    fun sample5() {
        // 类型别名
        val a: MyType = "webabcd"
        appendMessage("${a is MyType}, ${a is String}, ${a::class.simpleName}") // true, true, String

        // 内联类
        var b: MyInlineClass = MyInlineClass("webabcd")
        appendMessage("${b.name}") // webabcd
    }
    // 用 value 修饰的类就是内联类,必须要有 @JvmInline
    // 内联类要求在主构造函数中声明一个属性,内联类其实就是这个属性的包装
    // 这个存在的意义就是,对于基本类型的内联类来说,其会由 heap 上分配改为 stack 上分配,从而提高性能
    @JvmInline
    value class MyInlineClass(val name: String)

    // 定义一个 object 用于实现静态属性和静态方法
    object MyStatic {
        var name = "wanglei"
        fun hello(name: String): String {
            return "hello: $name"
        }
    }

    // 定义一个嵌套类,即类中的类(不可以访问外部类的成员)
    class NestedClass(name: String) {
        var name = ""
        init {
            this.name = name
        }
        fun hello(): String {
            return "hello: $name"
        }
    }

    // 定义一个内部类,内部类其实就是用 inner 修饰的嵌套类
    // 内部类可以访问外部类的成员
    inner class InnerClass(name: String) {
        var name = ""
        init {
            this.name = name
        }
        fun hello(): String {
            // 可以访问外部类的成员
            this@Demo7.appendMessage("我是内部类")
            return "hello: $name"
        }
    }



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

\kotlin\Demo7_Class.kt

/**
 * 本例用于演示类的定义(类,构造函数,属性,方法,属性的 getter 和 setter,下标,通过伴生对象实现静态属性和静态方法,扩展方法,扩展属性)
 *
 * 别管是类,还是属性,还是方法其可见性默认都是 public 的,除了 public 外还有 private, protected, internal(同项目可见)
 * var, val, const val, lateinit 也适用于属性,其概念参见 Demo1.kt 中的说明
 * kotlin 中的类名和包名可以与物理路径不一致(java 是要求一致的)
 */

package com.webabcd.androiddemo.kotlin

// 这里的 constructor 用于定义类的主构造函数,主构造函数只能有一个
// 对于 public 的类来说,其主构造函数可以省略 constructor
// 主构造函数的参数定义中,可以加上 var 或 val,其会自动声明同名的属性
class Demo7_Class constructor(name: String, var country: String) {

    // 声明属性
    var name: String = ""
    var age: Int = -1

    // 调用主构造函数时会执行这里
    init {
        this.name = name
    }

    // 非主构造函数,这个可以有多个
    // 后面跟 : this() 用于调用主构造函数
    constructor(name: String, age: Int, country: String) : this(name, country) {
        this.age = age
    }

    // 方法
    fun getInfo(): String {
        return "name:$name, age:$age, country:$country, weight:$weight, height:$height"
    }

    // 属性
    // 下面的代码就是 getter 和 setter 的默认实现,可以不写
    // 这里的 field 是由系统管理的,相当于 _weight
    var weight: Int = -1
        get() = field
        set(value) {
            field = value
        }

    // 属性,自定义 getter 和 setter
    var height: Int = -1
        get() = if (field < 10) 10 else field
        set(value) {
            field = value * 2
        }

    // 下标运算符(subscript operator)[]
    // 在 kotlin 中通过如下的 operator fun get 和 operator fun set 的方式实现 []
    var dict: MutableMap<Int, String> = mutableMapOf()
    operator fun get(index: Int): String {
        return dict[index] ?: ""
    }
    operator fun set(index: Int, value: String) {
        dict[index] = value
    }


    // 伴生对象
    // 用于为主类定义静态属性和静态方法
    companion object {
        var name = "wanglei"
        fun hello(name: String): String {
            return "hello: $name"
        }
    }
}

// 扩展方法
fun Demo7_Class.myExtensionMethod(): String { return "my extension method" }
// 扩展属性
val Demo7_Class.myExtensionProperty: String
    get() = "my extension property"
// 为伴生对象扩展方法
fun Demo7_Class.Companion.myCompanionExtensionMethod(): String { return "my companion extension method" }
// 为伴生对象扩展属性
val Demo7_Class.Companion.myCompanionExtensionProperty: String
    get() = "my companion extension property"

/layout/activity_kotlin_demo7.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:11  webabcd  阅读(54)  评论(0编辑  收藏  举报