Swift properties / getters setters

Hi,


I can create stored properties for eg lastName, firstName.


var lastName: String

var firstName: String

...


But what in case if I want eg:

- if I want to have the possibility to change the lastName and/or firstName during the lifecycle of the object.

- test if the passed value for lastName and/or firstName is empty or not


What is the way to do this in Swift?


Thanks.

Guy


Answered by OOPer in 87590022

Your code converted to Swift:

public class Person {
    private var _id: Int = 0
    private var _lastName: String = ""

    public init(id: Int, lastName: String) {
        self.id = id
        self.lastName = lastName
    }

    public var id: Int {
        get {
            return self._id;
        }
        set {
            if newValue < 0 || newValue > 1000 {
                // Swift setter cannot throw error.
                fatalError("invalid value for id")
            } else {
                self._id = newValue
            }
        }
    }

    public var lastName: String {
        get {
            return self._lastName
        }
        set {
            // In Swift, non-optional String can never get nil.
            if newValue.isEmpty {
                fatalError("invalid value for lastName")
            } else {
                self._lastName = newValue
            }
        }
    }
}

I believe this code fulfills your demand:

This code let's you test 1) if the passed in values are correct and 2) give the possibility to change a value when needed.


You may need to reconstruct your error handling strategy in Swift, but defining properties does not seem to be different.

class MyClass {
    var lastName: String
    var firstName: String

    init(lastName: String, firstName: String) {
        self.lastName = lastName
        self.firstName = firstName
    }
}
let object = MyClass(lastName: "Taro", firstName: "Yamada")
//- if I want to have the possibility to change the lastName and/or firstName during the lifecycle of the object.
object.lastName = "Hanako"
object.firstName = "Sato"
//- test if the passed value for lastName and/or firstName is empty or not
if object.lastName.isEmpty || object.firstName.isEmpty {
    print("empty")
}

I may be mistaking the intention of your question, if so, please be more specific about what you really want to do.

I think he's complaining about the fact (at least I think it's a fact - maybe you could confirm) that if you want to override get and set then it has to be a computed property, not a stored property. And I suppose you would need a separate private stored property so the computed property's getter and setter would have something to do.


class TestProperties {
    private var storedProperty: String = ""
    var someProperty: String {
        get {
            // possibly modify the return value
            return storedProperty + " modified"
        }
        set {
            // possibly modify the value being stored
            storedProperty = "foo " + newValue
        }
    }
}

let test = TestProperties()
test.someProperty = "bar"
print("\(test.someProperty)")  // "foo bar modified"


I suppose there is willSet / didSet on a stored property but nothing on the getter side.

Thanks. To clarify a little bit what I'm looking for in Swift, see the code below (C#). In Java this would be almost the same. This code let's you test 1) if the passed in values are correct and 2) give the possibility to change a value when needed.


Remark: this is only an example to show what I would like to achieve, normally eg you wouldn't change the id of a person object.


Thanks.


public class Person

{

private int id;

private string lastName;

public Person(int id, string lastName) -> corresponds with init(...)

{

Id = id;

LastName = lastName;

}

public int Id

{

get

{

return this.id;

}

set

{

if (value < 0 || value > 1000)

{

// throw error

}

else

{

this.id = value;

}

}

}

public string LastName

{

get

{

return this.lastName;

}

set

{

if (value == null)

{

// throw error

}

else

{

this.lastName = value;

}

}

}

}

Accepted Answer

Your code converted to Swift:

public class Person {
    private var _id: Int = 0
    private var _lastName: String = ""

    public init(id: Int, lastName: String) {
        self.id = id
        self.lastName = lastName
    }

    public var id: Int {
        get {
            return self._id;
        }
        set {
            if newValue < 0 || newValue > 1000 {
                // Swift setter cannot throw error.
                fatalError("invalid value for id")
            } else {
                self._id = newValue
            }
        }
    }

    public var lastName: String {
        get {
            return self._lastName
        }
        set {
            // In Swift, non-optional String can never get nil.
            if newValue.isEmpty {
                fatalError("invalid value for lastName")
            } else {
                self._lastName = newValue
            }
        }
    }
}

I believe this code fulfills your demand:

This code let's you test 1) if the passed in values are correct and 2) give the possibility to change a value when needed.


You may need to reconstruct your error handling strategy in Swift, but defining properties does not seem to be different.

Hi,


Thanks.

I suppose another option to implement the behavior could be:


private var lastName: String = ""

public func getLastName() -> String {

return self.lastName;

}


public func setLastName(description: String) {

if description.isEmpty {

fatalError("invalid value for lastName")

} else {

self.lastName = lastName

}

}

If this is so what is the 'recommended' way to implement the required behavior?

Thanks.

Guy

I believe it's just `another` way of doing the same thing. Generally, it is hard to find getters with their names begin with `get` in Apple's frameworks, so you can take it as `not recommended`.

But Swift is a new language and it seems not to be having so many established `recommended`.


Since Swift 2 introduced new error handling, using `throws` is being a preferred way for many programmers.

    enum PersonError: ErrorType {
        case InvalidLastName
    }
   
    private(set) var lastName: String = ""
    func setLastName(lastName: String) throws {
        if lastName.isEmpty {
            throw PersonError.InvalidLastName
        } else {
            self.lastName = lastName
        }
    }

Find your own `recommended` way and introduce it to other developers.

Swift properties / getters setters
 
 
Q