Dhanish Gajjar
Dhanish Gajjar

Reputation: 13

Swift 3.0 - Calling functions based on each case of 2 different enums

I am new and still learning. For practise I wanted to try an idea and see if I am able to model something on my own. For example if I have 2 sets of data in enums

protocol Pet {
   var type: PetType { get }
}

protocol PetType {}

enum Cat: PetType {
   case indoor
   case outdoor
}

enum Dog: PetType {
   case small
   case medium
   case large
}

struct MyPet: Pet {
   let type: PetType
   let age: Int
}

For each case there is a specific function of calculating age in human years that will execute. So if I create an instance

let garfield = myPet(type: Cat.indoor, age: 3)
myPet.inHumanYears

It should execute the correct function.

I tried a few things, but my knowledge seems limited for now. Can anyone guide / teach of how can I solve this?

Thank you.

Upvotes: 1

Views: 72

Answers (2)

azizj
azizj

Reputation: 3777

There are couple of ways. If the the human years will be unique (i.e., an outdoor cat will never have the same human years as an indoor cat), you can extend Int and just use rawValue. Otherwise, you're right with your approaach and you could do this:

Unique human years

import UIKit

protocol Pet {
    var type: PetType { get }
}

protocol PetType {
    var humanYears: Int { get}
}

enum Cat: Int, PetType {
    case indoor = 1
    case outdoor = 10
    
    var humanYears: Int {
        return self.rawValue
    }
}

enum Dog: Int, PetType {
    case small = 40
    case medium = 1
    case large = 4
    
    var humanYears: Int {
        return self.rawValue
    }
    
}

struct MyPet: Pet {
    let type: PetType
    let age: Int
}

let garfield = MyPet(type: Cat.indoor, age: 3)
garfield.type.humanYears

Duplicate human years

import UIKit

protocol Pet {
    var type: PetType { get }
}

protocol PetType {
    var humanYears: Int { get}
}

enum Cat: PetType {
    case indoor
    case outdoor
    
    var humanYears: Int {
        switch self {
        case .indoor: return 4
        case .outdoor: return 5
        }
    }
}

enum Dog: PetType {
    case small
    case medium
    case large
    
    var humanYears: Int {
        switch self {
        case .small:
            if (yearIs1960) {
                return 10
            }
            else {
                return 8
            }
        case .medium: return 5
        case .large: return 5
        }
    }
}

struct MyPet: Pet {
    let type: PetType
    let age: Int
}

let garfield = MyPet(type: Cat.indoor, age: 3)
garfield.type.humanYears

Here's a really good article by Benedikt Terhechte that goes into depth with examples on the possibilities with enums

Upvotes: 0

Federico Ojeda
Federico Ojeda

Reputation: 768

enum is a powerful type in swift. What is really cool is that it can have functions and properties that depend on which self (case) it is. By adding some properties to the enum you could do what you intend.

Your code would look something like this:

protocol Pet {
   var type: PetType { get }
}

protocol PetType {
  func inHumanYears(age: Int) -> Int
}

enum Cat: PetType {
   case indoor
   case outdoor

   func inHumanYears(age: Int) -> Int {
     switch self {
     case .indoor:
       //return you calculations for indoor
     case .outdoor:
         //return you calculations for outdoor
     }
   }
}

enum Dog: PetType {
   case small
   case medium
   case large

   func inHumanYears(age: Int) -> Int {
     switch self {
     case .small:
       //return you calculations for small
     case .large:
        //return you calculations for large
     case .medium:
       //return you calculations for medium
     }
   }
}

struct MyPet: Pet {
   let type: PetType
   let age: Int

   var inHumanYears: Int {
     return type.inHumanYears(age: age)
   }
}

The PetType checks which case of the enum it is itself and calculates accordingly. Then you can do:

let garfield = MyPet(type: Cat.indoor, age: 3)
print(garfield.inHumanYears)

Hope it helps!

Upvotes: 1

Related Questions