j b
j b

Reputation: 5296

How do I restrict a property to a range?

There are a cases where I might want to model data where it makes sense for a value to be restricted to a given range.

For example, if I want to represent a "mammal", I might want to restrict a legs property to 0–4.

My first attempt is shown below:

class Mammal {
    var _numLegs:Int?

    var numLegs:Int {
    get {
        return _numLegs!
    }
    set {
        if 0...4 ~= newValue {
            self._numLegs = newValue
        }
        else {
            self._numLegs = nil
        }
    }
    }
}

However, this seems unsatisfactory since all properties are "public" there is nothing stopping the customer of the class from setting Mammal._numLegs to some arbitrary value.

Any better ways to do it?

Upvotes: 6

Views: 3345

Answers (2)

Jack
Jack

Reputation: 16855

In this specific case, you want a property observer, you could implement it like this:

class Mammal {
    init () {
        numLegs = 0
        super.init()
    }
    var numLegs:Int {
        didSet: {
            if !(numLegs ~= 0...4) {
               numLegs = max(0,min(numLegs,4)) // Not sure if this is what you want though
            }   
        }
    }
}

Looking at this though, I'm not sure if this would recurse and call didSet again...I guess it wouldn't be too bad because it would pass the check the second time

Upvotes: 5

Jean Le Moignan
Jean Le Moignan

Reputation: 22236

Just for fun I decided to write a snippet with @jackWu's suggestion (+1) in order to try that didSet thing:

class Mammal {
    var numLegs:UInt? {
        didSet { if numLegs? > 4 { numLegs = nil } }
    }

    init() {
        numLegs = nil
    }
}

It works perfectly. As soon as you try to set numLegs to 5 or greater, boom, it gets nilled automatically. Please note that I used Uint to avoid negative leg quantities :)

I really like the elegance of didSet.

Upvotes: 8

Related Questions