更新时间:2022-10-14 20:03:24
问题与类型擦除无关,如果您删除 struct AnyAnimal< Food>
定义,则会得到相同的
错误消息。
如果您从 struct Cow
然后
中删除 feed()
方法,编译器无法推断关联的类型食品
。因此,无论您
在默认实现中使用了一个具体类型:
extension动物{
func feed食物:草) - > Void {
print(unknown)
}
}
struct Cow:Animal {
}
或者使用
的默认实现为每个类型定义一个类型别名 Food
:
extension动物{
func feed(food:Food) - > Void {
print(unknown)
}
}
struct Cow:Animal {
typealias Food = Grass
}
也可以为 Food
定义一个默认类型>在
协议中:
协议动物{
associatedtype Food = Grass
func feed (食物:食物) - >无效
}
扩展动物{
func feed(food:Food) - > Void {
print(unknown)
}
}
struct Cow:Animal {
}
I have been struggling very hard with Swift Protocols and Associated Types for a long time. I started again with basic to really understand what is going wrong and I followed this article of TypeErasure in Swift Protocols with Associated Type Requirement by Rob Napier but still i have no luck.
Find the code below
// An Animal can eat
protocol Animal {
associatedtype Food
func feed(food: Food) -> Void
}
struct AnyAnimal<Food>: Animal {
private let _feed: (Food) -> Void
init<Base: Animal where Food == Base.Food>(_ base: Base) {
_feed = base.feed
}
func feed(food: Food) { _feed(food) }
}
// Kinds of Food
struct Grass {}
struct Cow: Animal {
func feed(food: Grass) { print("moo") }
}
struct Goat: Animal {
func feed(food: Grass) { print("bah") }
}
let grassEaters = [AnyAnimal(Cow()), AnyAnimal(Goat())]
for animal in grassEaters {
animal.feed(Grass())
}
Now i wanted to give a default implementation in the protocol Animal like below
extension Animal {
func feed(food: Food) -> Void {
print("unknown")
}
}
And when i removed the function from the struct Cow i get the error message that Cow doesn't conform to Protocol Animal.
Does that mean you cannot have Type Erasures and Default Implementation together?. Is there any way where i can do TypeErasure and also keep a Default Implementation?
The problem is unrelated to the type erasure and you'll get the same
error message if you remove the struct AnyAnimal<Food>
definition.
If you remove the feed()
method from struct Cow
then
the compiler cannot infer the associated type Food
. So either you
use a concrete type in the default implementation:
extension Animal {
func feed(food: Grass) -> Void {
print("unknown")
}
}
struct Cow: Animal {
}
or you define a type alias Food
for each type using the
default implementation:
extension Animal {
func feed(food: Food) -> Void {
print("unknown")
}
}
struct Cow: Animal {
typealias Food = Grass
}
It is also possible to define a default type for Food
in the
protocol:
protocol Animal {
associatedtype Food = Grass
func feed(food: Food) -> Void
}
extension Animal {
func feed(food: Food) -> Void {
print("unknown")
}
}
struct Cow: Animal {
}