protocol AnimalFeed {
init()
}
protocol Animal {
associatedtype Feed: AnimalFeed
func eat(_ food: Feed)
}
struct Hay: AnimalFeed {}
struct Carrot: AnimalFeed {}
struct Cow: Animal {
func eat(_ food: Hay) {
print("I eat hay")
}
}
struct Rabbit: Animal {
func eat(_ food: Carrot) {
print("I eat carrot")
}
}
struct Farm {
func feed<T: Animal>(_ animal: T) {
animal.eat(T.Feed())
}
func feedAll<T: Animal>(_ animals: [T]) {
animals.forEach { feed($0)}
}
}
let farm = Farm()
farm.feed(Rabbit())
farm.feedAll([Cow(), Rabbit()])
最后一行導致錯誤:沒有更多背景關系的運算式型別不明確 我們如何解決這個問題?我希望能夠傳遞一個符合 Animal 協議的結構陣列。
uj5u.com熱心網友回復:
這不能在 Swift 5.5 中完成
當你寫
func feedAll<T: Animal>(_ animals: [T]) {
animals.forEach { feed($0)}
}
你是說,“農場可以喂一組任何一種動物。” 編譯器查找符合 Animal、Cow 和 Rabbit 的單一型別,但找不到。你真正想要的是,“Farm 可以提供一組符合 Animal 的任何物件。”
func feedAll(_ animals: [Animal]) {
animals.forEach { feed($0) }
}
但這激怒了 Swift 5.5
協議“Animal”只能用作通用約束,因為它具有 Self 或關聯的型別要求
協議“動物”作為一種型別不能符合協議本身
您可以通過構造一個“盒子”型別來解決此問題,該型別捕獲內部型別(通常稱為型別擦除)并將陣列中的每個動物顯式包裝在一個盒子中。例如
struct AnimalFeeder {
let feed: () -> Void
init<T: Animal>(_ animal: T) {
feed = {
animal.eat(T.Feed())
}
}
}
func feedAll(_ animals: [AnimalFeeder]) {
animals.forEach { $0.feed() }
}
farm.feedAll([AnimalFeeder(Cow()), AnimalFeeder(Rabbit())])
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/489143.html
