Home > OS >  Why my property do not change dynamically?
Why my property do not change dynamically?

Time:08-16

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 fullNamedoes 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

  • Related