首页 Kotlin学习笔记(5) - 属性
文章
取消

Kotlin学习笔记(5) - 属性

一、属性声明

Kotlin 中的属性使用var声明为可变属性,val声明位只读属性

1
2
3
4
5
6
7
class Address {
    var name: String = "Holmes, Sherlock"
    val street: String = "Baker"
    var city: String = "London"
    var state: String? = null
    val zip: String = "123456"
}

属性的完整语法格式如下,初始化、getter、setter都是可选的,如果类型可以推导出来的话,类型也可以省略

1
2
3
var <propertyName>[: <PropertyType>] [= <property_initializer>]
    [<getter>]
    [<setter>]

可以自定义getter、setter的访问器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var stringRepresentation: String
    get() = this.toString()
    set(value) {
        setDataFromString(value) 
    }


class Rectangle(val width: Int, val height: Int) {
    val area: Int 
        get() = this.width * this.height
  
  	//当类型可以推导时,也可以简写成这样
		val area get() = this.width * this.height
}


如果需要修改访问器的可见性或添加注解时可以像下面这样

1
2
3
4
5
var setterVisibility: String = "abc"
    private set // the setter is private and has the default implementation

var setterWithAnnotation: Any? = null
    @Inject set // annotate the setter with Inject

在访问器中使用当前属性时应该获取当前作用域下的field字段,被称为“ backing fields”

1
2
3
4
5
6
var counter = 0 // 这个初始器直接为幕后字段赋值
    set(value) {
        if (value >= 0)
            field = value
            // counter = value // ERROR StackOverflow: Using actual name 'counter' would make setter recursive
    }

二、编译期常量

如果属性在编译期已经是已知的,那应该使用const关键字进行标记。添加const需要满足以下几个条件

  • 必须是顶级属性 或 声明为object 或是伴生对象
  • 必须以String 或 原生类型进行初始化
  • 不可以自定义getter

三、属性的延迟初始化

通常来说声明为非空类型则必须在构造函数中进行初始化,这样可能会带来一些不便,例如可能通过依赖注入的方式进行初始化,这种情况下可以使用lateinit进行标记,告知我们要延迟初始化

1
2
3
4
5
6
7
8
9
10
11
public class MyTest {
    lateinit var subject: TestSubject

    @SetUp fun setup() {
        subject = TestSubject()
    }

    @Test fun test() {
        subject.method()  // dereference directly
    }
}

需要 lateinit 不可以用在原生类型上,如:Int,Float等

如需要检查lateinit是否进行了初始化,可以调用.isInitialized方法,注意::符号

1
2
3
if (foo::bar.isInitialized) {
    println(foo.bar)
}
本文由作者按照 CC BY 4.0 进行授权

Kotlin学习笔记(4) - 继承

Kotlin学习笔记(6) - 接口