Last active
June 12, 2022 09:43
-
-
Save protspace/eaeebc090d2c4c16466e45418cad0afb to your computer and use it in GitHub Desktop.
Design protocol interfaces in Swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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