I have a class like this:
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
}
}
}
Why fullName
does not change if I change the firstName
like:
val person1 = User("Mark", "Zuck")
println(person1.fullName)
//Mark Zuck
person1.firstName = "Bill"
println(person1.firstName)
//Bill
println(person1.fullName)
//Mark Zuck
person1.lastName = "Gates"
println(person1.fullName)
//prints Mark Zuck
Is it because fullName
are bounded by getters and setters that's why the only way to change it is by accessing fullname
directly???
CodePudding user response:
when we say
get() = "Name: $field"
it just return the value that have been initialize during the instantiation, to fix that I just change it to
get() = "$firstName $lastName"
so that it calculates again and return the updated value
full code:
var fullName = "$firstName $lastName"
get() = "$firstName $lastName"
set(value){
field = value
}
CodePudding user response:
Have a read of this: Getters and setters - basically because you're referring to field
in your getter (and the setter), there's a backing field storing a value. And your getter (which is a function) is reading from that backing field when it calculates a value to return.
The code you posted as an answer:
var fullName = "$firstName $lastName"
get() = "$firstName $lastName"
set(value){
field = value
}
is pretty much equivalent to this:
val fullName get() = "$firstName $lastName"
because your getter never references the backing field. Your setter really does nothing - it stores the value you pass in the backing field, but that field is never read. If you remove the reference to the backing field:
var fullName
get() = "$firstName $lastName"
set(value){ }
then no backing field is created, because your getter and setter both do their own thing without involving the field. So you don't need to initialise it with a value - there's no field to initialise! The getter was never using it anyway.
And since your setter does nothing, you may as well delete it and make your property a val
since you could never (directly) change its value anyway - fullName = "Some Guy"
had no visible effect, so making it a var
is pretty misleading!
And that's how you end up with a simple getter that returns a value derived from other properties:
val fullName get() = "$firstName $lastName"
If you wanted, you could make that setter update firstName
and lastName
:
var fullName
get() = "$firstName $lastName"
set(value){
// you'd need to handle the possible errors here
val names = value.split(' ')
firstName = names[0]
lastName = names[1]
}
Again that's not using a backing field, the data is stored somewhere else (in firstName
and lastName
in this case) and the getter and setter are just functions that handle storing and retrieving the data in some form. This is just an example, you probably wouldn't want to do this here (updating firstName
and lastName
directly is way better and less work to handle) but this is just to show you could! Sometimes you do this kind of thing with a setter