Kotlin中val属性为何可变更?自定义RecyclerView适配器疑问
mySelectedIndex没有报错? 先帮你理清楚核心问题:你混淆了Kotlin中val属性的不可变性范围,咱们一步步拆解:
首先回顾你的场景:
Code B是带有单选按钮的自定义RecyclerView适配器。在Code A的
fun methodA()和fun methodB()中均修改了mCustomAdapter,因此get() = mCustomAdapter.getSelectedIndex()的引用也发生变化,这意味着val属性mySelectedIndex从不同地址获取值。我认为val属性不可被修改,为何应用未出现报错?Code A代码片段:
private lateinit var mCustomAdapter: CustomAdapter private val mySelectedIndex get () = mCustomAdapter.getSelectedIndex()
1. val限制的是“属性本身不能被赋值”,不是“返回值不能变”
Kotlin里的val关键字,本质是禁止对属性本身进行重新赋值,而不是要求它返回的值必须固定不变。
- 对于普通的val属性(比如
val name = "Alice"),它背后有一个隐藏的存储字段,getter默认返回这个固定值,而且你不能写name = "Bob"这种赋值操作。 - 但你的
mySelectedIndex是一个计算属性(computed property)——它没有自己的存储字段,每次你访问它的时候,都会执行get()里的代码,去调用mCustomAdapter.getSelectedIndex()获取最新值。val在这里只限制了你不能做mySelectedIndex = 10这种直接赋值的操作,完全允许getter动态返回不同结果。
2. 修改mCustomAdapter的引用,完全符合val的规则
你在methodA()和methodB()里修改的是mCustomAdapter这个var变量的引用(比如把它换成一个新的CustomAdapter实例),但mySelectedIndex的getter只是每次去拿当前mCustomAdapter实例的选中索引而已。
你从来没有给mySelectedIndex本身赋值,只是每次访问它时,它去动态获取最新的结果——这完全在val的规则允许范围内,所以不会报错。
3. 举个简单的类比例子
看这段代码,完全合法且符合预期:
var count = 0 val currentCount get() = count fun main() { println(currentCount) // 输出0 count++ println(currentCount) // 输出1 }
这里currentCount是val,但它的返回值会随着count的变化而变化——因为每次访问都会执行getter逻辑,而val只禁止你给currentCount直接赋值,比如currentCount = 5这种操作才会报错。
总结
你的mySelectedIndex作为计算属性,val的作用只是阻止你直接给它赋值,而它的getter可以自由地动态返回不同的结果,这完全符合Kotlin的语法规则,所以应用不会报错。
内容的提问来源于stack exchange,提问作者HelloCW

