另一个答案很好地解释了新some关键字的技术方面,但这个答案将试图简单地解释为什么。
假设我有一个协议动物,我想比较两个动物是否是兄弟姐妹:
protocol Animal {
func isSibling(_ animal: Self) -> Bool
}
这样,如果两个动物是同一类型的动物,那么比较它们是否是兄弟姐妹才有意义。
现在我举一个动物的例子供大家参考
class Dog: Animal {
func isSibling(_ animal: Dog) -> Bool {
return true // doesn't really matter implementation of this
}
}
没有T的方式
现在,假设我有一个函数,从一个“家族”中返回一个动物。
func animalFromAnimalFamily() -> Animal {
return myDog // myDog is just some random variable of type `Dog`
}
注意:这个函数实际上不会编译。这是因为在添加'some'特性之前,如果协议使用'Self'或泛型,则不能返回协议类型。但是假设你可以…假设这将myDog向上转换为抽象类型Animal,让我们看看会发生什么
现在问题来了,如果我试着这么做:
let animal1: Animal = animalFromAnimalFamily()
let animal2: Animal = animalFromAnimalFamily()
animal1.isSibling(animal2) // error
这将抛出一个错误。
为什么?原因是,当你调用animal1.isSibling(animal2)时,Swift不知道这些动物是狗、猫还是什么。据斯威夫特所知,animal1和animal2可能是不相关的动物物种。因为我们不能比较不同类型的动物(见上文)。这会出错
某个T如何解决这个问题
让我们重写之前的函数:
func animalFromAnimalFamily() -> some Animal {
return myDog
}
let animal1 = animalFromAnimalFamily()
let animal2 = animalFromAnimalFamily()
animal1.isSibling(animal2)
animal1和animal2不是Animal,但它们是实现Animal的类。
这让你现在做的是,当你调用animal1. issibling (animal2)时,Swift知道animal1和animal2是同一类型。
所以我喜欢这样思考:
一些T让Swift知道T的什么实现正在被使用,但类的用户不知道。
(自我推销免责声明)我已经写了一篇博客文章,更深入地讨论了这个新功能(例子和这里一样)