一手遮天 Android - kotlin: 类相关 1(基础)
一手遮天 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>