1

I have the following enum in Swift:

enum Animal {
    case Cat(name: String, color: String)
    case Dog(name: String, tailLength: Double)
    case Cow(name: String, isBrown: Bool)
}

Is there a way to get the name of an Animal without a switch that matches each case one by one? Something like:

func animalName(a: Animal) -> String {
    // This does not work, you have to use a switch
    return a.name
}
Nick Keets
  • 3,240
  • 1
  • 14
  • 13

3 Answers3

1

If all animal types have a name property, then I think it would be better to make that explicit.

enum AnimalType {
    case Cat(color: String)
    case Dog(tailLength: Double)
    case Cow(isBrown: Bool)
}

struct Animal {
    let name: String
    let type: AnimalType
}

I think the above would be better than @JanGreve's answer because it allows you to simply do:

func animalName(a: Animal) -> String {
    // Now the below will work.
    return a.name
}

It's far easier to pull the name out of the object this way because you don't need to do a if case or switch case.

Daniel T.
  • 32,821
  • 6
  • 50
  • 72
0

Not as far as I know - without modification of the enum (e.g. taking use of inheritage or usage of a protocol (like, in this case maybe Printable))

Edit as to accomodate comment:

If you are free to define the data structure, you might use something like this:

enum Animal {
    case Cat(color: String)
    case Dog(tailLength: Double)
    case Cow(isBrown: Bool)
}
enum NamedAnimal {
    case NamedAnimal(name: String, animal:Animal)
}

edit two:

func namedAnimalName(namedAnimal:NamedAnimal) -> String {
    switch namedAnimal {
      case .NamedAnimal(let n, _): return n
    }
}
Tobi Nary
  • 4,566
  • 4
  • 30
  • 50
  • I can modify the enum as needed, I just want to avoid the switch because the list of animals can be long and may also be updated often. – Nick Keets Nov 23 '15 at 11:43
  • In that case, think about making the enum a single case with the name and a second enum detailing it's type – Tobi Nary Nov 23 '15 at 11:48
  • how to use it? how to define func animalName(a: Animal) -> String or func animalName(a: NamedAnimal) -> String ??? – user3441734 Nov 23 '15 at 11:58
  • 1
    I updated my answer again to accomodate the second question from @user3441734 – Tobi Nary Nov 23 '15 at 12:03
  • 1
    Don't make NamedAnimal an enum. Make it a struct with two properties instead. IMHO – Daniel T. Nov 23 '15 at 12:20
  • @DanielT. we are still circling. why do you think that struct is better then 'one case' enum? we still don't have the 'right' answer, possibly because it doesn't exists. – user3441734 Nov 23 '15 at 12:38
  • @user3441734 I posted my reasons as an answer. – Daniel T. Nov 23 '15 at 13:57
  • @user3441734: right. As I mentioned, there is no perfect anwer for this, just working around. – Tobi Nary Nov 23 '15 at 13:59
  • @JanGreve check my 'solution'. it is not too smart, but fulfill OP requirements (i hope so ..) – user3441734 Nov 23 '15 at 14:44
  • That is just horrible. relying on the framework's implementation of Printable for Enum is just bad and error prone. – Tobi Nary Nov 23 '15 at 15:08
  • there is no 'Printable' in the language now and this behavior is well documented. – user3441734 Nov 23 '15 at 15:40
  • It may still be subject to change -- using the string representation of a data structure to access a part of is just seems like a horrible idea to me, not only performance-wise, but also safety-wise. – Tobi Nary Nov 23 '15 at 15:43
-1
enum Animal {
    case Cat(name: String, color: String)
    case Dog(name: String, tailLength: Double)
    case Cow(name: String, isBrown: Bool)
}

let a1: Animal = .Cat(name: "cica", color: "black")
let a2: Animal = .Dog(name: "dunco", tailLength: 10.2)


func animalName(a: Animal)->String {
    return "\(a)".characters.split("\"").map(String.init)[1]
}

animalName(a1) // "cica"
user3441734
  • 16,722
  • 2
  • 40
  • 59