Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enums with data in swift

Tags:

enums

swift

I would like to use java-like enums, where you can have enum instances with custom data. For instance:

enum Country {
    case Moldova(capital: "Chișinău", flagColors: [Color.Blue, Color.Yellow, Color.Red]);
    case Botswana(capital: "Gaborone", flagColors: [Color.Blue, Color.White, Color.Black]);
}

I could later write:

Country.Moldova.capital;

It seems that I can indicate the variables, but not the values, and I can only assign the values when using the enum, not declaring. Which would be the best way to mimic this behaviour?

like image 894
André Fratelli Avatar asked Jul 09 '14 08:07

André Fratelli


2 Answers

you can do something like this, which may be helpful: (that is a very generic example only)

enum Country : Int {
    case Moldova, Botwana;

    //

    func capital() -> String {
        switch (self) {
        case .Moldova:
            return "Chișinău"
        case .Botwana:
            return "Gaborone"
        default:
            return ""
        }
    }

    //

    func flagColours() -> Array<UIColor> {
        switch (self) {
        case .Moldova:
            return [UIColor.blueColor(), UIColor.yellowColor(), UIColor.redColor()]
        case .Botwana:
            return [UIColor.blueColor(), UIColor.whiteColor(), UIColor.blackColor()]
        default:
            return []
        }
    }

    //

    func all() -> (capital: String, flagColours: Array<UIColor>) {
        return (capital(), flagColours())
    }

    //

    var capitolName: String {
    get {
        return capital()
    }
    }

    //

    var flagColoursArray: Array<UIColor> {
    get {
        return flagColours()
    }
    }

}

then you can access to the details like this:

let country: Country = Country.Botwana

get the capital

that way:

let capital: String = country.capital()

or another:

let capital: String = country.all().capital

or a third one:

let capital: String = country.capitolName

get the flag's colours:

that way:

let flagColours: Array<UIColor> = country.flagColours()

or another:

let flagColours: Array<UIColor> = country.all().flagColours

or a third one:

let flagColours: Array<UIColor> = country.flagColoursArray
like image 133
holex Avatar answered Oct 05 '22 01:10

holex


Here is another generic example that is similar to the one posted by holex, but a bit closer to how it looks in Java. (I like it because all of the custom data is in one place). Instead of switching on 'self' in separate methods, I simply create a static dictionary that maps each case to a tuple containing the appropriate data. Then, I have convenience var's to get at the data easily.

enum TestEnum {
    case One
    case Two
    case Three

    private static let associatedValues = [
        One:    (int: 1, double: 1.0, string: "One"),
        Two:    (int: 2, double: 2.0, string: "Two"),
        Three:  (int: 3, double: 3.0, string: "Three")
    ]

    var int: Int {
        return TestEnum.associatedValues[self]!.int;
    }

    var double: Double {
        return TestEnum.associatedValues[self]!.double;
    }

    var string: String {
        return TestEnum.associatedValues[self]!.string;
    }
}

You can access the custom data like so:

println(TestEnum.One.int)      // 1
println(TestEnum.Two.double)   // 2.0
println(TestEnum.Three.string) // Three
like image 33
Matthew Gharrity Avatar answered Oct 05 '22 02:10

Matthew Gharrity