Skip to content

Instantly share code, notes, and snippets.

@protspace
Last active June 12, 2022 09:43
Show Gist options
  • Save protspace/eaeebc090d2c4c16466e45418cad0afb to your computer and use it in GitHub Desktop.
Save protspace/eaeebc090d2c4c16466e45418cad0afb to your computer and use it in GitHub Desktop.
Design protocol interfaces in Swift
//
// File.swift
// SP
//
// Created by Yevgen Sagidulin on 12.06.2022.
//
import Foundation
protocol AnimalFeed {
associatedtype CropType: Crop where CropType.FeedType == Self
static func grow() -> CropType
}
protocol Crop {
associatedtype FeedType: AnimalFeed where FeedType.CropType == Self
func harvest() -> FeedType
}
struct Alfalfa: Crop {
func harvest() -> Hay {
print("Alfalfa harverst -> Hay 🧻")
return Hay()
}
}
struct Hay: AnimalFeed {
static func grow() -> Alfalfa {
print("Alfalfa grow 🌿")
return Alfalfa()
}
}
struct GrassBucket: AnimalFeed {
static func grow() -> Grass {
print("Gtass grow 🌱")
return Grass()
}
}
struct Grass: Crop {
func harvest() -> GrassBucket {
print("Just making grass bucket out of grass 💐")
return GrassBucket()
}
}
protocol Animal {
associatedtype Feed: AnimalFeed
func eat(_ food: Feed)
}
struct Horse: Animal {
func eat(_ food: Hay) {
print("horse eating \(food)")
}
}
struct Rebbit: Animal {
func eat(_ food: GrassBucket) {
print("rebbit eating \(food)")
}
}
struct Farm {
func feed(_ animal: some Animal) {
let crop = type(of: animal).Feed.grow()
let food = crop.harvest()
animal.eat(food)
}
// This works only in app (bug in Playground)
// func feedAll_swift60(_ animals: [any Animal]) {
// animals.forEach { feed($0) }
// }
func feedAll_swift57(_ animals: [any Animal]) {
animals.forEach { animal in
if animal is Horse {
feed(Horse())
} else if animal is Rebbit {
feed(Rebbit())
}
}
}
}
let animals: [any Animal] = [
Horse(),
Horse(),
Rebbit(),
]
let farm = Farm()
farm.feedAll_swift57(animals)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment