Kotlin学习笔记3-2 类和对象-属性和字段

属性和字段

Kotlin官网:Classes and Objects-Properties and Fields

属性声明

类中可以声明属性。var可变,val只读。

class Student{
    val name = "Tom"
    var age = 12
}

使用方法和Java中的字段相同,对象.属性名

class Tom {
    val name = "Tom"
    var age = 12
}

fun tomGrowup(tom: Tom) {
    tom.age++
    println(tom.name)
    println(tom.age)
}

Getter和Setter

定义属性的完整格式

var <propertyName>[: <PropertyType>] [= <property_initializer>]
    [<getter>]
    [<setter>]
var/val 属性名 : 属性类型 = 初始化
    get() = ...
    set(value) = ...

类型、初始化、访问器都是可省略的。
类型在可以被推导出时可以省略:初始化代码中推导出类型,1.1开始getter可以推导出类型。
只读属性和可变的有两个区别:1使用val声明,2不允许setter。
setter和getter可以在属性声明中自定义。
setter的参数约定俗成使用value,也可以自定义名字。
当使用访问器默认实现但需要添加修饰时,可以只写set/get关键字。

class Student {
    var name = "LiLei"
    var age = 12
        private set //使用默认set实现,只添加访问限制
    val gender:Int? = 0
    var adult //省略初始化
    get() = age>12
    set(value){
        if(value&&age<18){
            age = 18
        }
    }
}

后备字段

类中无法直接定义字段,Kotlin自动提供后备字段。
使用field关键字调用。
field关键字只能在访问器中使用。
filed只有被使用了才会被生成,如使用默认访问器,在自定义访问器中使用了field。

var counter = 0 // the initializer value is written directly to the backing field
    set(value) {
        if (value >= 0) field = value
    }
//这种情况不会生成field
val isEmpty: Boolean
    get() = this.size == 0

field存在的意义是解决访问器中访问属性,如果在setter中写成这样

var counter = 0 // the initializer value is written directly to the backing field
    set(value) {
        if (value >= 0) counter = value
    }

写成属性=值实际上是在setter中调用了setter赋值,循环调用,相当于Java中

void set(int value){
    if(value>=0) set(value);
}

会出现栈溢出错误。field就相当于”属性的this”。

后备属性

后备字段不满足需求时可以使用后备属性

private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
    get() {
        if (_table == null) {
            _table = HashMap() // Type parameters are inferred
        }
        return _table ?: throw AssertionError("Set to null by another thread")
    }

编译期常量

在编译期值确定的属性可以定义为编译期常量。
使用const关键字定义。
必须满足下面的要求:
* 顶级元素;对象的成员
* 字符串;基本类型
* 没有自定义getter

编译期常量可以在注解中使用

const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"

@Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { ... }

延迟初始化的属性和变量

某些情况下属性不能立刻初始化,如注入的对象,单元测试等,可以修为延迟初始化。
关键字lateinit,可修饰类体中的var属性。不能在主构造函数中,属性不能有自定义访问器。
1.2之后顶级属性和局部变量必须是非空且不能为基本类型。
在延迟初始化的属性被初始化之前访问会抛出UninitializedPropertyAccessException异常。

延迟初始化变量的初始化检查(1.2后支持)

使用isInitialized判断。

if (foo::bar.isInitialized) {
    println(foo.bar)
}

属性重写

见3-1属性重写

属性代理

见3-13属性代理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值