Kotlin中val与var声明计算属性的差异及相关编译疑问
Kotlin计算属性val与var的差异解析
关于val计算属性是否违背本意
首先明确:Kotlin里的val核心是只读,不是“值永远固定不变”。
你写的第一种方式:
val currentQuestionResId: Int get() = questionBank[qIdx].textResId
这是标准的只读计算属性,外部代码只能通过get()获取它的值,根本没法直接给它赋值。虽然每次调用get()返回的结果可能随qIdx或questionBank的变化而改变,但这完全符合val的设计初衷——禁止外部写入,只允许读取。所以完全没有违背val的本意。
为什么var计算属性要求初始化
这是因为var默认会隐式生成幕后字段(backing field),即使你写了自定义getter,编译器默认还是认为这个属性需要一个存储值的字段。而var是可写的,编译器要求必须初始化这个幕后字段,否则它不知道属性的初始状态是什么。
如果你想让var的计算属性不依赖幕后字段,必须同时自定义getter和setter,并且在setter里也不使用默认的field变量。比如:
var currentQuestionResId: Int get() = questionBank[qIdx].textResId set(value) { // 自行实现赋值逻辑,比如根据传入值修改qIdx qIdx = questionBank.indexOfFirst { it.textResId == value } }
这样编译器就不会要求初始化了,因为你已经完全接管了属性的读写逻辑,不需要默认的幕后字段。如果只写getter不写setter,编译器还是会认为需要幕后字段来存储值,所以必须初始化。
内容的提问来源于stack exchange,提问作者user3463521
相关产品推荐
相关产品推荐

