Swift Protocols with Associated Type Requirement and Default Implementation

烂漫一生 提交于 2020-01-01 16:24:09

问题


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?


回答1:


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 {
}


来源:https://stackoverflow.com/questions/36810270/swift-protocols-with-associated-type-requirement-and-default-implementation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!