安卓系列之 kotlin 基础知识(四)

180 阅读3分钟

类的超类是 Any 类,Any 类有 equals()、 hashCode() 与 toString()这三个方法,相当于 Java 的 Object 类。

定义类

  • 格式
    class 类名 [可见性修饰符][注解] [constructor] (Params){ }

定义一个类,赋予属性值,自动生成 get 和 set 方法,若有特殊处理,则可以重写 get 和 set 方法。
主构造函数没有任何注解或者可见性修饰符,可以省略 constructor 关键字。

  1. val 定义的属性值只有 get 方法
  2. var 定义的属性值有 set 和 get 方法
class Teacher {
    //性别 var定义的属性值有get和set方法
    var sex: Int = 1

    //国家 val定义的属性值只有get方法
    val nation: String = "中国"
}

可见型修饰符

  1. private
    意味着只在这个类内部(包含其所有成员)可见;
  2. protected
    在子类中可见
  3. internal
    能见到类声明的 本模块内 的任何客户端都可见其 internal 成员;
  4. public
    能见到类声明的任何客户端都可见其 public 成员。

field 关键字

只在 get 和 set 方法中使用。

class Teacher {
    //姓名
    var nameString? = null
        get() = field?.uppercase()
        set(value) {
            field = value?.trim()
        }

    //年纪
    var ageInt = 18
        get() {
            return field + 1
        }
        set(value) {
            field = value + 1
        }
}

计算属性

类内部自动生成的属性

class Teacher {

    //幸运号码 计算属性
    val luckyNo
        get() = (1..100).random()
}

属性解构

component 函数

//类属性解构
class Book(var type: Intval name: String) {
    operator fun component1() = type
    operator fun component2() = name
}

fun testBook() {
    val (type, name) = Book(1"数学")
    print("$type is $name")
}

类比较

==在类比较的时候也是比较引用,因为类的超类的是 Any 类

class Student(
    _name: String,
    var age: Int,
    var sex: Int = 1
) {
    var name = _name
        get() = field.lowercase()

    constructor(name: String) : this(name, 181) {
        this.name = name.trim()
    }

}

fun test() {
    //==,比较引用,类继承Any类,所以这里也是引用
    //===,比较引用
    print(Student("小明") == Student("小明"))//false
    print(Student("小明") === Student("小明"))//false
}

类初始化

主构造函数

  1. 临时变量使用下划线加变量名
  2. 更推荐使用定义变量的方式作为参数
class Student(
    _name: String,//临时变量使用下划线
    var age: Int,//直接定义变量的方式作为参数,更推荐这种方案
    var sex: Int = 1//默认参数,使用时不传入这个值则使用默认1
) {
    //只赋值一次
    var name = _name
        get() = field.lowercase()

}

fun test() {
    val student = Student("Elaine"181)
    print("name:" + student.name)
    print("age:" + student.age)
}

次构造函数

使用 constructor 关键字,在主构造函数之上传入默认值,然后可以将传入的值进行初始化操作。次构造函数必须直接或者间接地委托到主构造函数,使用关键字 this。

class Student(
    _name: String,
    var age: Int,
    var sex: Int
) {
    var name = _name
        get() = field.lowercase()

    //次构造函数
    constructor(name: String) : this(name, 181) {
        this.name = name.trim()//定义初始化代码
    }

    //次构造函数
    constructor(name: String, age: Int) : this(name, age, 1)

}

fun test() {
    val student = Student("Elaine")
    print("name:" + student.name)
    print("age:" + student.age)
}

初始化代码块 init

对传入的参数进行特殊处理,比如空判断等

class Student(
    _name: String,
    var age: Int,
    var sex: Int = 1
) {
    var name = _name
        get() = field.lowercase()

    //初始化代码块
    init {
        //验证名字是否为空
        require(_name.isNotEmpty()) { print("name is empty") }
    }
}

fun test() {
    val student = Student("")
}

初始化顺序

  1. 主构造函数里声明的属性
  2. 类级别的属性赋值或者 init 初始化块里的属性赋值和函数调用(看谁写在前面谁先执行)
  3. 次构造函数里的属性赋值和函数调用

图片

顺序

延迟初始化和惰性初始化

  1. 延迟初始化:
    使用 lateinit 关键字,需要主动进行初始化或者判断属性是否初始化了
class Student(
    _name: String,
    var age: Int,
    var sex: Int = 1
) {
    var name = _name
        get() = field.lowercase()

    constructor(name: String) : this(name, 181) {
        this.name = name.trim()
    }

    //延迟初始化变量,需要主动初始化
    lateinit var myClass: String

    //报名课程
    fun getClass() {
        myClass = "math"
    }

    //开始学习
    fun startLearn() {
        //判断课程是否初始化了,是则开始学习
        if (::myClass.isInitialized) print("开始学习《$myClass》")
    }
}

fun test() {
    val student = Student("Elaine")
    student.getClass()
    student.startLearn()
}
  1. 惰性初始化:
    当调用惰性初始化的值的时候,才会去初始化,类似单例模式里的懒汉模式
class Student(
    _name: String,
    var age: Int,
    var sex: Int = 1
) {
    var name = _name
        get() = field.lowercase()

    constructor(name: String) : this(name, 181) {
        this.name = name.trim()
    }

    //惰性初始化,当调用这个属性值的时候才去初始化
    val run by lazy {
        getReadyForRun()
    }

    private fun getReadyForRun(): String {
        print("我已经穿好运动鞋了")
        return "我可以跑了"
    }
}

fun test() {
    val student = Student("Elaine")
    student.run//调用了才初始化
}

继承和方法重写

使用关键字 open 开放父类以及类的方法

  1. is 关键字进行类型判断
  2. as 关键字进行类型转换
open class People(_type: String) {
    var type = _type
    open fun eat() {
        Log.e("people""吃米饭")
    }
}

//子类继承父类
class Older : People("老人") {
    //重新方法
    override fun eat() {
        Log.e("people""吃偏软的米饭")
    }

    fun walk() {
        Log.e("people""散步")
    }
}

fun testPeople() {
    val people: People = Older()
    people.eat()//打印结果:people: 吃偏软的米饭

    //类型判断
    print(people is People)//true
    print(people is Older)//true

    //类型转换
    if (people is Older) {
        (people as Older).walk()
    }
}

object 关键字

定义只能产生一个实例的类。

  1. 对象声明
//一个类,是单例
object SingleManager {
    //类方法
    fun getSingleName(): String {
        return "单例名字"
    }
}

fun testSingleManager() {
    print(SingleManager.getSingleName())
}
  1. 表达式
//对象
open class Phone {
    open fun call() = "可以打电话"
}

fun testPhone() {
    //表达式
    val androidPhone = object : Phone() {
        override fun call(): String = "安卓手机可以打电话"
    }
    print(androidPhone.call())
}
  1. 伴生对象
    一个类只能有一个伴生对象,使用关键字 companion object
//伴生对象
open class LuckNum {

    companion object {
        private const val luckyNo = "10008"

        fun load() = "测试 $luckyNo"
    }

}

fun testLuckNum() {
    LuckNum.load()
}

项目 github 地址

github.com/ElaineTaylo…

若帅哥美女对该系列文章感兴趣,可微信搜索公众号(木子闲集)关注更多更新文章哦,谢谢~