8

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?

3 Answers 3

16

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
Sign up to request clarification or add additional context in comments.

1 Comment

This is what I ended up doing, although I don't think that it's ideal, it does mimmic the behaviour I was looking for.
3

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

1 Comment

I really like this solution because it keeps each enum data in a single line. Have you figured out how to get the compiler to check that all the cases are covered in associatedValues?
2

Unfortunately it seems like enums with raw values are limited to literal values. You may want to file a bug.

As an alternative, you could do something like this:

let Country = (
    Moldova: (capital: "Chișinău", flagColors: [Color.Blue, Color.Yellow, Color.Red]),
    Botswana: (capital: "Gaborone", flagColors: [Color.Blue, Color.White, Color.Black])
)

or this:

struct Country {
    let capital: String
    let flagColors: [Color]
}

let Countries = (
    Moldova: Country(capital: "Chișinău", flagColors: [.Blue, .Yellow, .Red]),
    Botswana: Country(capital: "Gaborone", flagColors: [.Blue, .White, .Black])
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.