将泛型参数限制为从协议继承的协议

时间:2017-09-17 04:00:50

标签: swift generics inheritance protocols

我不确定where子句可以将通用参数限制为从某个协议继承的协议。

protocol Edible {}
protocol PetFood: Edible {}
struct CatFood: PetFood {}
struct Rocks {}

func eat<T: Edible>(_ item: T) -> String {
    return "Just ate some \(type(of: item))"
}

let food: CatFood = CatFood()
eat(food) //"Just ate some CatFood"

let moreFood: PetFood = CatFood()
//eat(moreFood) //Cannot invoke 'eat' with an argument list of type '(PetFood)'

func eatAnything<T>(_ item: T) -> String {
    return "Just ate some \(type(of: item))"
}

eatAnything(moreFood) //This works, obviously
eatAnything(Rocks()) //But, of course, so does this...

有没有办法限制eatAnything()允许协议类型,但只限制那些从Edible继承的协议类型?

1 个答案:

答案 0 :(得分:1)

在您的示例中,泛型函数的定义没有任何意义,因为它可以替换为:

EntrySet

但是如果你真的想使用泛型函数那么你应该知道:

  1. 通用功能的定义

    • func eat(_ item: Edible) -> String { return "Just ate some \(type(of: item))" }
    • func eat<T: Edible>(_ item: T) -> String { ... }
    • func eat<T>(_ item: T) -> String where T: Edible { ... }
  2. 协议是动态类型,因此它们使用后期绑定。通用代码在编译期间转换为正常,需要早期绑定

    • 早期绑定 (编译时):在运行期间运行变量之前已知类型,通常是通过静态的声明性方式
    • 后期绑定 (运行时):在运行期间执行变量之前,类型是未知的;通常通过分配,但还有其他方式强制一种类型;动态类型语言将此称为基础特征
  3. 可以使用与协议兼容的类型定义通用函数,但是此函数不能将此协议作为类型传递,因为编译器不知道该类型是什么{{ 1}}。传递给泛型函数类型必须是特定类型(class,struct,enum,...)

  4. func eat<T: Edible>(_ item: T) -> String where T: Equatable { ... }