當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
}