今天开始kotlin第三节内容:属性和字段
1,声明属性:
Kotlin中的属性可以用var声明为可变的,也可以用val声明为只读的
class Address{
var name : String= "Tom"
var age : Int= 0
var sex : String?
}
要使用一个属性,只要用名称引用它即可
class CopyAddress(name : String) : Address{
val address= Address();//创建对象
var name= address.name//将调用访问器
var age : Int= address.age
}
2,Getters 与 Setters
a:声明一个属性的完整语法是:
var 属性名:属性类型 = 初始化器
getter方法
setter方法
。。。。。。。。。
其中初始化器,getter,setter方法都是可选的,如果属性的返回值类型可以从初始化器或者getter方法推断出来,则可以省略
var allByDefault: Int? // 错误:需要显式初始化器,隐含默认 getter 和 setter
var age = 20//类型int,默认getter,setter方法
b:自定义getter,setter
var stringResponding : String
get()= this.toString()
set(value){
setDataFromString(value) // 解析字符串并赋值给其他属性
}
3,幕后字段
kotlin 中类不可以有字段 , 但是使用自定义访问器时 , kotlin 提供了一个自动幕后字段 , 通过 field 访问
field 幕后字段只可以在自定义访问器中使用
var a = 12//初始值会直接赋值给幕后字段field
get(){
//直接引用field做判断
return if(field >=0) field else -field
}
set(value){
//使用传入的值做判断
if(value>100){
println("赋值大于100,默认的field还为 $field")
}
}else{
field = value
printin("赋值成功:$field")
}
4,幕后属性
通过默认 getter setter 访问私有属性会被优化 , 不会引入函数调用开销
private var _map: Map<String, Int>? = null
public val map: Map<String, Int>
get() {
if(_map == null){
_map = HashMap() // 类型推断
}
return _map ?: throw AssertionError("Set to null by another thread")
}
5,延迟初始化属性与变量
一般情况下 , 属性声明为非空类型必须要在构造函数中初始化 , 然而 , 属性可以通过依赖注入初始化 , 或者可以通过单元测试 setu() 初始化
这种情况下 , 不能在构造函数中提供非空的初始化器 , 又想在引用时避免空检查
就可以使用 lateinit 延迟初始化属性和变量
class Person{
lateinit var name: String
//通过setup方法或者注解等初始化
@Setup fun setUp(){
name = "tim"
}
@Test
fun show(){
print(name) // 因为 name 是 String非空类型 , 所以此时调用就避免了空检查 , 打印 tim
}
}
注意
1.lateinit 只能用于类体中的属性,不能是主构造函数中的属性,也不能有自定义访问器getter setter
2.kotlin1.2之后,可以用于顶层属性和局部变量
3.该属性必须是非空类型,不能是原生类型
4.该属性初始化之前访问,会抛出异常UninitializedPropertyAccessException
6,检测一个lateinit var是否已经初始化
Kotlin1.2 之后可以 检测一个 lateinit var 是否已经初始化
只需要在该属性的引用上使用 .isInitialized
class Person {
lateinit var name: String
fun show(){
if(::name.isInitialized){
print(name)
}else{
println("name 还未初始化")
}
}
}