Kotlin使用apply时属性与函数参数同名如何正确赋值
Kotlin apply作用域同名属性赋值报错解决方案
问题复现
触发报错的代码如下:
data class Foo( var aaa: String, var bbb: String ) fun bar(aaa: String) { Foo().apply { aaa = aaa // 该行IDE抛出错误 bbb = "bbb" } }
IDE抛出错误提示:Val cannot be reassigned。
错误原因
这个报错和属性修饰符无关,核心是Kotlin的标识符解析规则:
- 函数参数属于当前函数的局部变量,解析优先级高于作用域函数的隐式接收者成员属性
apply块内未加前缀的同名标识符aaa,会被优先识别为外层bar函数的入参aaa,而非Foo实例的属性- Kotlin函数参数默认是
val修饰的不可变值,不允许重新赋值,因此触发报错
补充说明:示例中Foo类的属性已经修正为
var修饰,如果属性本身用val修饰,无论哪种写法都无法在apply作用域内修改该属性。
可行解决方案
- 方案1:显式指定接收者指向实例属性(最常用)
给赋值目标加上接收者前缀,明确告诉编译器等号左侧是Foo实例的属性,等号右侧自动解析为外层函数参数,无歧义:
如果存在多层嵌套的作用域函数,可以使用带标签的fun bar(aaa: String) { Foo().apply { this.aaa = aaa bbb = "bbb" } }this明确指定接收者,避免嵌套场景下的解析错误:fun bar(aaa: String) { Foo().apply { this@apply.aaa = aaa bbb = "bbb" } } - 方案2:重命名外层参数避免同名冲突
直接给函数入参设置和类属性不重名的命名,从根源上消除解析歧义,代码可读性更高:fun bar(aaaValue: String) { Foo().apply { aaa = aaaValue bbb = "bbb" } }
内容的提问来源于stack exchange,提问作者eth4io
相关产品推荐
相关产品推荐

