CommodityType /// The upper bound existential type for the associated type does not safety convert to the actual concrete type, because the concrete type is unknown. func eat(_: some FeedType) } //struct Chicken: Animal { // // func produce() -> Egg { // return Egg() // } // // func eat(_: FeedType) { // // } //} struct Cow: Animal { func produce() -> Milk { return Milk() } func eat(_: Hay) {} } protocol Food { } struct Egg: Food { } struct Milk: Food { } struct Farm { /// This strategy of using the same representation for different concrete types is called type erasure. var animals: [any Animal] func produceCommodities() -> [any Food] { return animals.map { animal in animal.produce() } } } protocol AnimalFeed { } struct "> CommodityType /// The upper bound existential type for the associated type does not safety convert to the actual concrete type, because the concrete type is unknown. func eat(_: some FeedType) } //struct Chicken: Animal { // // func produce() -> Egg { // return Egg() // } // // func eat(_: FeedType) { // // } //} struct Cow: Animal { func produce() -> Milk { return Milk() } func eat(_: Hay) {} } protocol Food { } struct Egg: Food { } struct Milk: Food { } struct Farm { /// This strategy of using the same representation for different concrete types is called type erasure. var animals: [any Animal] func produceCommodities() -> [any Food] { return animals.map { animal in animal.produce() } } } protocol AnimalFeed { } struct "> CommodityType /// The upper bound existential type for the associated type does not safety convert to the actual concrete type, because the concrete type is unknown. func eat(_: some FeedType) } //struct Chicken: Animal { // // func produce() -> Egg { // return Egg() // } // // func eat(_: FeedType) { // // } //} struct Cow: Animal { func produce() -> Milk { return Milk() } func eat(_: Hay) {} } protocol Food { } struct Egg: Food { } struct Milk: Food { } struct Farm { /// This strategy of using the same representation for different concrete types is called type erasure. var animals: [any Animal] func produceCommodities() -> [any Food] { return animals.map { animal in animal.produce() } } } protocol AnimalFeed { } struct ">
import UIKit
var greeting = "Hello, playground"
protocol Animal {
associatedtype CommodityType: Food
// associatedtype CommodityType
associatedtype FeedType: AnimalFeed
func produce() -> CommodityType
/// The upper bound existential type for the associated type does not safety convert to the actual concrete type, because the concrete type is unknown.
func eat(_: some FeedType)
}
//struct Chicken: Animal {
//
// func produce() -> Egg {
// return Egg()
// }
//
// func eat(_: FeedType) {
//
// }
//}
struct Cow: Animal {
func produce() -> Milk {
return Milk()
}
func eat(_: Hay) {}
}
protocol Food {
}
struct Egg: Food {
}
struct Milk: Food {
}
struct Farm {
/// This strategy of using the same representation for different concrete types is called type erasure.
var animals: [any Animal]
func produceCommodities() -> [any Food] {
return animals.map { animal in
animal.produce()
}
}
}
protocol AnimalFeed { }
struct Hay: AnimalFeed { }
let animals: [any Animal] = [Cow()]
/// Type erasure does not allow us to work with associated types in consuming position.
animals.map { animal in
animal.eat(<#T##Animal.FeedType#>)
}