Kotlin如何编写自定义getter并保留属性直接访问语法
Kotlin 属性访问与自定义getter问题解答
1. client?.personalInfo 是否调用getter?
Kotlin的属性默认做了封装,不存在直接公开字段访问的情况,你用client?.personalInfo语法访问属性永远都是调用该属性的getter方法,哪怕是默认生成的无自定义逻辑的getter也不例外。
你在主构造函数里声明的val personalInfo: PersonalInfo?,Kotlin会自动生成两个内容:
- 一个private的幕后字段存储属性值
- 一个public的getter方法,返回该幕后字段的值
所以不存在直接访问类字段的情况。
2. 自定义getPersonalInfo()方法报错的原因
Kotlin编译为JVM字节码时,属性personalInfo的默认getter会被编译为签名和你手写的fun getPersonalInfo():PersonalInfo?完全一致的方法,因此会报方法签名重复的错误。
你将主构造参数加private修饰后,自动生成的getter也会变为private,和你手写的public方法不再冲突,因此报错消失,但此时外部无法通过client?.personalInfo访问属性,不符合需求。
3. 带自定义getter的正确实现
可以实现添加print逻辑同时保留client?.personalInfo访问语法的需求,不需要手动写getPersonalInfo()方法,直接自定义属性的getter即可,正确代码如下:
class Client(personalInfo: PersonalInfo?) { // 将构造参数赋值给属性的幕后字段 val personalInfo: PersonalInfo? = personalInfo get() { // 必须用field关键字访问幕后字段,直接写personalInfo会递归调用getter导致栈溢出 print("personal info $field") return field } }
如果担心构造参数和属性名重复导致误用,可以给构造参数改名区分,写法更清晰:
class Client(_personalInfo: PersonalInfo?) { val personalInfo: PersonalInfo? = _personalInfo get() { print("personal info $field") return field } }
以上写法实现了每次访问personalInfo属性都会触发print逻辑,同时完全保留了原有的属性访问语法。
内容的提问来源于stack exchange,提问作者Violetta
相关产品推荐
相关产品推荐

