为何Kotlin中User类的fullName无法随firstName/lastName动态变化?
问题:修改firstName/lastName后fullName不更新的原因及解决方法
代码示例
User类定义
open class User(var firstName: String, var lastName: String) { var fullName = "$firstName $lastName" get() = "Name: $field" set(value){ if(value.startsWith("Jon")){ field = "Jon Doe" }else{ field = value } } }
测试代码
val person1 = User("Mark", "Zuck") println(person1.fullName) // 输出:Name: Mark Zuck person1.firstName = "Bill" println(person1.firstName) // 输出:Bill println(person1.fullName) // 输出:Name: Mark Zuck person1.lastName = "Gates" println(person1.fullName) // 输出:Name: Mark Zuck
用户疑问
修改firstName或lastName时,fullName并未随之变化,是因为fullName被getter和setter绑定,只能通过直接访问fullName来修改它吗?
解答
问题原因
你当前的fullName只是在类初始化时,把当时的firstName和lastName拼接结果赋值给了幕后字段field。之后修改firstName或lastName时,不会自动更新field的值,而fullName的getter只是返回基于这个静态field的字符串,自然不会跟着变化。这和getter/setter绑定无关,是初始化逻辑没有建立动态关联导致的。
解决方案
根据需求,有两种常见处理方式:
方式1:动态计算fullName(推荐)
如果希望fullName始终反映最新的firstName和lastName,可以去掉fullName的字段存储,让getter每次调用时动态拼接:
open class User(var firstName: String, var lastName: String) { var fullName: String get() = "Name: $firstName $lastName" set(value) { // 可选:支持通过设置fullName反向修改firstName和lastName val nameContent = if (value.startsWith("Name: ")) value.substring(6) else value if (nameContent.startsWith("Jon")) { firstName = "Jon" lastName = "Doe" } else { val parts = nameContent.split(" ", limit = 2) if (parts.size == 2) { firstName = parts[0] lastName = parts[1] } } } }
这样每次获取fullName时,都会用当前最新的firstName和lastName生成结果,修改这两个属性后,fullName会自动同步更新。
方式2:修改firstName/lastName时手动更新fullName
如果需要保留fullName的字段存储(比如有自定义setter逻辑),可以给firstName和lastName添加setter,在它们被修改时同步更新fullName:
open class User(firstName: String, lastName: String) { var firstName: String = firstName set(value) { field = value // 更新fullName的字段值 fullName = "$firstName $lastName" } var lastName: String = lastName set(value) { field = value // 更新fullName的字段值 fullName = "$firstName $lastName" } var fullName = "$firstName $lastName" get() = "Name: $field" set(value){ if(value.startsWith("Jon")){ field = "Jon Doe" }else{ field = value } } }
这种方式下,修改firstName或lastName会触发它们的setter,进而更新fullName的幕后字段,确保getter返回最新值。
内容的提问来源于stack exchange,提问作者James Gosling
相关产品推荐
相关产品推荐

