当protocol中带有associatedtype或者Self约束时,这个协议就不能被当作一个独立的类型使用了,例如:
在没有这些约束的时候,我们可以这样写:
protocol Food {}
protocol Animal {
func eat(_ food: Food)
}
func isDangerous(animal: Animal) -> Bool {
if animal is Tiger {
return true
}
return false
}
但是如果给Animal添加了associatedtype
protocol Animal {
associatedtype F: Food
func eat(_ food: F)
}
此时在写出上面isDangerous的代码时,回报错
protocol 'Animal' can only be used as a generic constraint because it has Selfor associated type requirements
这是因为 Swift 需要在编译时确定所有类型,这里因为Animal包含了一个不确定的类型,所以随着Animal本身类型的变化,其中的F将无法确定 (试想一下如果在这个函数内部调用eat的情形,你将无法指定eat参数的类型)。在一个协议加入了像是associatedtype或者Self的约束 后,它将只能被用为泛型约束,而不能作为独立类型的占位使用,也失去了动态派发的特性。也 就是说,这种情况下,我们需要将函数改写为泛型:
func isDangerous<T: Animal>(animal: T) -> Bool {
if animal is Tiger {
return true
}
return false
}