首页 文章

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

提问于
浏览
2

很长一段时间以来,我一直在努力使用Swift协议和关联类型 . 我从基本开始再次真正了解出现了什么问题,我在Rob Napier的Swift Protocols中使用了相关类型要求的TypeErasure article,但我仍然没有运气 .

找到下面的代码

// 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())
}

现在我想在协议Animal中给出一个默认实现,如下所示

extension Animal {

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

当我从struct Cow中删除该函数时,我得到了Cow不符合Protocol Animal的错误消息 .

这是否意味着你不能同时使用Type Erasures和Default Implementation?有什么方法我可以做TypeErasure并保持默认实现?

1 回答

  • 6

    该问题与类型擦除无关,如果删除 struct AnyAnimal<Food> 定义,您将收到相同的错误消息 .

    如果从 struct Cow 中删除 feed() 方法,则编译器无法推断关联类型 Food . 所以要么在默认实现中使用具体类型:

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

    或者使用默认实现为每种类型定义类型别名 Food

    extension Animal {
        func feed(food: Food) -> Void {
            print("unknown")
        }
    }
    
    struct Cow: Animal {
        typealias Food = Grass
    }
    

    也可以在协议中为 Food 定义默认类型:

    protocol Animal {
        associatedtype Food = Grass
        func feed(food: Food) -> Void
    }
    
    
    extension Animal {
        func feed(food: Food) -> Void {
            print("unknown")
        }
    }
    
    struct Cow: Animal {
    }
    

相关问题