具有关联类型需求和默认实现的Swift协议 [英] Swift Protocols with Associated Type Requirement and Default Implementation

查看:122
本文介绍了具有关联类型需求和默认实现的Swift协议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很长一段时间,我一直在用Swift协议和相关类型非常努力地努力。我重新开始了基本的工作,以真正了解发生了什么问题,并且我遵循这个有关关联类型的Swift协议中TypeErasure的文章罗布纳皮尔的要求,但我仍然没有运气。



找到下面的代码

  //动物可以吃
协议动物{
相关类型食物
func feed(食物:食物) - > 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)}
}

//各种食物
struct Grass {}

struct Cow:Animal {
func feed(food:Grass){print(moo)}
}

struct Goat:Animal {
func feed(food:Grass){print(bah) }
}

让grassEaters = [AnyAnimal(Cow()),AnyAnimal(Goat())]
for grassEaters {
animal.feed(Grass ())
}

现在我想在协议Animal中给出一个默认实现以下

 扩展动物{

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

当我从结构牛中删除函数时,我得到了Cow不符合协议动物的错误消息。



这是否意味着您不能使用Type Erasures和默认实现在一起?有什么办法可以做TypeErasure并保持默认实现?

解决方案

问题与类型擦除无关,如果您删除 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 {
}

这篇关于具有关联类型需求和默认实现的Swift协议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆