Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 582
j b Avatar asked Jun 13 '14 18:06

j b


2 Answers

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.

like image 188
Jean Le Moignan Avatar answered Jan 04 '23 12:01

Jean Le Moignan


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

like image 28
Jack Avatar answered Jan 04 '23 10:01

Jack