简体   繁体   English

具有关联类型要求和默认实现的Swift协议

[英]Swift Protocols with Associated Type Requirement and Default Implementation

I have been struggling very hard with Swift Protocols and Associated Types for a long time. 很长一段时间以来,我一直在努力使用Swift协议和关联类型。 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. 我再次使用基本功能来真正理解出现了什么问题,我在Rob Napier的Swift Protocols中使用了相关类型要求的TypeErasure 文章 ,但我仍然没有运气。

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 现在我想在协议Animal中给出一个默认实现,如下所示

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. 当我从struct Cow中删除该函数时,我得到了Cow不符合Protocol Animal的错误消息。

Does that mean you cannot have Type Erasures and Default Implementation together?. 这是否意味着你不能同时使用Type Erasures和Default Implementation? Is there any way where i can do TypeErasure and also keep a Default Implementation? 有什么方法我可以做TypeErasure并保持默认实现?

The problem is unrelated to the type erasure and you'll get the same error message if you remove the struct AnyAnimal<Food> definition. 该问题与类型擦除无关,如果删除struct AnyAnimal<Food>定义,您将得到相同的错误消息。

If you remove the feed() method from struct Cow then the compiler cannot infer the associated type Food . 如果从struct Cow删除feed()方法,则编译器无法推断关联类型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: 或者使用默认实现为每种类型定义类型别名Food

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: 也可以在协议中为Food定义默认类型:

protocol Animal {
    associatedtype Food = Grass
    func feed(food: Food) -> Void
}


extension Animal {
    func feed(food: Food) -> Void {
        print("unknown")
    }
}

struct Cow: Animal {
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM