限制从协议继承的协议泛型参数
问题描述:
我不确定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
继承?
答
在你的榜样,一个泛型函数的定义并没有任何意义,因为它可以被替换为:
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 { ... }
func eat<T: Edible>(_ item: T) -> String where T: Equatable { ... }
-
协议是动态的类型,所以他们使用后期绑定。在编译过程中的通用代码被转换为正常,需要早期结合
- 早期绑定(编译时间):在运行时该变量被行使前,通常是通过一个静态的,声明性手段 类型是已知
- 延迟绑定(运行时间):类型是未知的,直到变量在运行期间被执行;通常是通过分配,但还有其他方式来强制类型;动态类型语言把这种潜在的功能
泛型函数可以是协议兼容的类型定义,但是这个功能无法通过此协议类型,因为编译器不知道是什么该类型是
T
。传递到泛型函数类型必须是特定类型(类,结构,枚举,...)
let a: [Int] = [1,2,3]
let b: [CustomStringConvertible] = [1, "XYZ"]
a.index(of: 2) // 1
b.index(of: "XYZ") // error
嗯,肯定的 - 它只是一个简单的例子来说明这个问题。 – andyvn22
@ andyvn22我更新了我的答案 –