Kotlin的属性和字段

作者: 程序员丶星霖 | 来源:发表于2019-11-07 09:47 被阅读0次

    Kotlin的属性相当于Java的字段再加上getter和setter方法。

    一、读写属性和只读属性

    Kotlin使用val定义只读属性,使用var定义读写属性,系统会为只读属性生成getter方法,会为读写属性生成getter和setter方法。

    Kotlin定义普通属性时,需要显式指定初始值:要么在定义时指定初始值,要么在构造器中指定初始值。

    class Address {
        var street: String = ""
        var city = ""
        var province = ""
        var postCode: String? = null
    }
    

    在定义属性时,如果系统可根据属性初识值推断出属性的类型,就可以不显式指定属性的类型。

    Kotlin定义一个属性,就相当于定义一个Java类的private修饰的field,以及public、final修饰的getter和setter方法。

    在Kotlin类中定义属性后,被Kotlin程序使用时只能使用点语法访问属性;被Java程序使用时只能通过getter、setter方法访问属性。

    1. 只读属性用val定义,读写属性用var定义;
    2. 只读属性不允许有setter方法。

    二、自定义getter和setter

    在定义属性时可指定自定义的getter和setter方法。

    定义getter、setter方法时无须使用fun关键字。

    fun main(args: Array<String>) {
        var user = User("亮", "诸葛")
        println(user.fullName)
    }
    
    class User(first: String, last: String) {
        var first: String = first
        var last: String = last
        val fullName: String
            //自定义getter方法
            get() {
                println("执行fullName的getter方法")
                return "${first}.${last}"
            }
    }
    
    

    输出结果:

    执行fullName的getter方法
    亮.诸葛
    

    对于只读属性来说,只能重写getter方法;对于读写属性来说,可根据需要重写其中之一,也可同时重写它们。

    fun main(args: Array<String>) {
        var user = User("亮", "诸葛")
        println(user.fullName)
        user.fullName = "懿.司马"
        println(user.first)
        println(user.last)
    }
    
    class User(first: String, last: String) {
        var first: String = first
        var last: String = last
        var fullName: String
            //自定义getter方法
            get() = "${first}.${last}"
            set(value) {
                println("执行fullName的setter方法")
                if ("." !in value || value.indexOf(".") != value.lastIndexOf(".")) {
                    println("输入的fullName不合法")
                } else {
                    var tokens = value.split(".")
                    first = tokens[0]
                    last = tokens[1]
                }
            }
    }
    
    

    输出结果:

    亮.诸葛
    执行fullName的setter方法
    懿
    司马
    

    三、幕后字段

    如果Kotlin类的属性有幕后字段,则Kotlin要求该属性显式指定初始值。

    满足以下条件,系统就会为属性生成幕后字段:

    • 该属性使用Kotlin自动生成的getter和setter方法或其中之一。
    • 重写getter、setter方法时,使用field关键字显式引用了幕后字段。
    fun main(args: Array<String>) {
        var p = Person("悟空", 29)
        p.age = 120
        println(p.age)
        p.age = 25
        println(p.age)
    }
    
    class Person(name: String, age: Int) {
        var name = name
            set(newName) {
                if (newName.length > 6 || newName.length < 2) {
                    println("您设置的人名不符合要求")
                } else {
                    field = newName
                }
            }
    
        var age = age
            set(newAge) {
                if (newAge > 100 || newAge < 0) {
                    println("您设置的年龄不合法")
                } else {
                    field = newAge
                }
            }
    }
    

    输出结果:

    您设置的年龄不合法
    29
    25
    

    四、幕后属性

    幕后属性就是用private修饰的属性,Kotlin不会为幕后属性生成任何getter、setter方法。

    fun main(args: Array<String>) {
        var p = Person("悟空", 29)
        println(p.name)
        p.name = "八戒"
        println(p.name)
    }
    
    class Person(name: String, age: Int) {
        private var _name = name
        var name
            get() = _name
            set(newName) {
                if (newName.length > 6 || newName.length < 2) {
                    println("您设置的人名不符合要求")
                } else {
                    _name = newName
                }
            }
    }
    

    输出结果:

    悟空
    八戒
    

    五、延迟初始化属性

    Kotlin提供了lateinit修饰符来解决属性的延迟初始化。使用lateinit修饰的属性,可以在定义该属性时和在构造器中都不指定初始值。

    lateinit修饰符有如下限制:

    • lateinit只能修饰在类体中声明的可变属性。
    • lateinit修饰的属性不能有自定义的getter或setter方法。
    • lateinit修饰的属性必须是非空类型。
    • lateinit修饰的属性不能是原生类型。

    如果在lateinit属性赋初始值之前访问它,程序将会引发“lateinit property name has not been initialized”异常。

    六、内联属性

    inline修饰符可修饰没有幕后字段的属性的getter或setter方法,既可单独修饰属性的getter或setter方法;也可修饰属性本身,相当于同时修饰该属性的getter和setter方法。

    fun main(args: Array<String>) {
        var product = Product()
        var name=product.author.name
        println(name)
    }
    
    class Name(name: String, desc: String) {
        var name = name
        var desc = desc
    }
    
    class Product {
        var productor: String? = null
        //inline修饰属性的getter方法,表明读取属性时会内联化
        val proName: Name
            inline get() = Name("Python", "当前热推语言")
        //inline修饰属性的setter方法,表明设置属性时会内联化
        var author: Name
            get() = Name("龟书", "一个大神")
            inline set(v) {
                this.productor = v.name
            }
        //inline修饰属性本身,表明读取和设置属性时都会内联化
        inline var pubHouse: Name
            get() = Name("开源社区", "无")
            set(v) {
                this.productor = v.name
            }
    }
    

    输出结果:

    龟书
    

    学海无涯苦作舟

    我的微信公众号.jpg

    相关文章

      网友评论

        本文标题:Kotlin的属性和字段

        本文链接:https://www.haomeiwen.com/subject/vrhdqctx.html