Kotlin 学习——属性和字段

时间:2023-02-06 15:43:15

    前面已经说过,Kotlin 的属性可以使用 val 或者 var 关键字标识的,val 声明属性是不可变的,只能读,而 var 是可变的,允许读和改变。而且在 Kotlin 中调用属性只需要向 Java 中的一样,使用实例调用即可:

class Demo{
    val isAlive = true
    var name:String = ""
    var age:Int = 0
    var sex:String=""
}

fun createDemo(mDemo: Demo):Demo{
    val demo = Demo()
    mDemo.name = demo.name
    mDemo.age = demo.age
    mDemo.sex = demo.sex

    return demo
}

    属性的完整写法(括号里面的可以省略):

var name(:Type)(?)(=init)
(getter)
(setter)
// 类似于下面这个
var name:String?="hhhh"

    当然,val 的属性只要可读性,是没有 setter 的,属性的 setter 和 getter 方法主要是用于对自身的改变,类似于拦截器,就是当你读数据或者是写数据时,它都会执行 getter 或者 setter 方法,比如下面这种写法:

class Demo{
    var name:String=""
         set(value) {
             field = "${value[0]}先生"
         }
}

fun main(args: Array<String>) {
    val demo = Demo()
    demo.name = "宋琪飞"
    println(demo.name)
}

    结果:

Kotlin 学习——属性和字段

    gettter 和 setter 都是对属性自身的处理,而 Kotlin 类中不能直接声明一个字段再来说明这个属性,这个时候就提供了一个 filed 关键字来引用这个字段(这个字段就是幕后字段),filed 只能在属性的访问器内使用,如果属性至少一个访问器使用默认实现,或者自定义访问器通过 filed 引用幕后字段,将会为该属性生成一个幕后字段。

    除了幕后字段,还有幕后属性,如果你想要的效果不太适用幕后字段,就可以使用幕后属性:

private var _table: Map<String, Int>? = null
    public val table: Map<String, Int>
        get() {
            if (_table == null) {
                _table = HashMap() // 类型参数已推断出
            }
            return _table ?: throw AssertionError("Set to null by another thread")
        }

    编译期常量:当熟悉需要满足位于顶层或者是 Object 的一个成员、使用原生类型初始化、没有自定义的 getter 时,可以使用 const 关键字标记为编译期常量。这些属性可以用在注解中:

const val MESSAGE:String = "MESSAGE"

@Deprecated(MESSAGE) fun answer(){}

    当属性通过依赖注入或者 SetUp 方法中初始化时,我们可以使用 lateinit 关键字标记属性,来延迟初始化属性和变量,在类体中引用属性时避免空检查:

lateinit var name:String

    在初始化前访问一个 lateinit 属性会抛出一个特定异常,该异常明确标识该属性被访问及它没有初始化的事实。如果要检测一个 lateinit 的属性有没有被初始化,可以在该属性的引用上使用 .isInitialized

class Demo{

}
class Test{
    lateinit var demo: Demo
    fun answer(){
        if (Test::demo.isLateinit){
            println("YES")
        }
    }

}