The public wrapper

Now that we have all of the components required to implement our public wrapper, let's have a look at what's left to do:

final class AnyAnimal<T>: Animal where T: Food {
typealias FoodType = T
private let box: _AnyAnimalBase<T>

init<A: Animal>(_ animal: A) where A.FoodType == T {
box = _AnyAnimalBox(animal)
}

// Call forwarding for implementing Animal
var preferredFood: T? {
get { return box.preferredFood }
set { box.preferredFood = newValue }
}

var name: String {
return box.name
}

func eat(food: T) {
box.eat(food: food)
}
}

Let's have a bit of fun now with our newly implemented type erasure pattern.

First, let's redefine our base types, Cow and Goat:

struct Cow: Animal {
var name: String
var preferredFood: Grass? = nil
}

struct Goat: Animal {
var name: String
var preferredFood: Grass? = nil
}

Then, as these two grass eaters eat the same way, we can provide a conditional default implementation on Animal:

extension Animal where FoodType: Grass {
func eat(food: FoodType) {
if let preferredFood = preferredFood,
type(of: food) == type(of: preferredFood) {
print("\(name): Yummy! \(type(of: food))")
} else {
print("\(name): I'm eating...")
}
}
}

Now all of the pieces are together and we can go to the pasture with our flock of grass eaters, and let them enjoy their favorite grass:

class Grass: Food {}
class Flower: Grass {}
class Dandelion: Grass {}
class Shamrock: Grass {}

let flock = [
AnyAnimal(Cow(name: "Bessie", preferredFood: Dandelion())),
AnyAnimal(Cow(name: "Henrietta", preferredFood: nil)),
AnyAnimal(Goat(name: "Billy", preferredFood: Shamrock())),
AnyAnimal(Goat(name: "Nanny", preferredFood: Flower()))
]

let flowers = [
Grass(),
Dandelion(),
Flower(),
Shamrock()
]

while true {
flock.randomElement()?
.eat(food: flowers.randomElement()!)
sleep(1)
}

Running this program should print something similar to the following:

Bessie: I'm eating...
Nanny: Yummy! Flower
Henrietta: I'm eating...
Bessie: I'm eating...
Billy: I'm eating...
Henrietta: I'm eating...
Nanny: I'm eating...
Nanny: Yummy! Flower
...