Swift:从Protocol到AssociatedType,然后从Type Erasure
动机
我们使用类来表示对称操作,例如“比较”,例如,如果我们想编写一个广义的排序或二进制搜索来比较两个元素,则最终结果如下:
我们对Ordered
的任意实例一无所知。 因此,如果该方法不是由子类实现的,那么除了trap之外,我们无能为力。 现在,这是我们正在与类型系统进行斗争的第一个迹象。 如果我们没有意识到这一点,那也是我们开始对自己撒谎的地方。 因为我们将问题搁置一旁,告诉自己,只要Order实现的每个子类都在前面,我们就可以了。 使其成为子类的问题。 因此,我们继续实施以下示例。
它具有双精度值,我们将覆盖优先级以进行比较。 other
只是任意有序,而不是数字。 因此,我们不知道other
具有价值属性。 我们将Other
为Number
以得到正确的类型进行比较。 这是一个静态的安全孔。 类不允许我们表达self
类型和他人类型之间的这种至关重要的类型关系。 这是一种代码气味。 因此,每当我们在代码中看到强制下降时,就表明一些重要的类型关系已经丢失,这通常是由于抽象类所致,这是一个好兆头。 显然,我们需要的是更好的抽象机制。
更好的抽象机制
抽象机制必须具有以下属性:
- 不强制接受隐式共享或丢失的类型关系
- 强制只选择一种抽象并在定义类型时进行
- 不会强制接受不需要的实例数据或相关的初始化复杂性
- 对于需要覆盖的内容,不会有任何歧义。
是的…!!! 协议具有所有这些属性。
不要从课堂开始。 从协议开始……!
Swift中面向协议的编程
制作Swift时,它是第一个面向协议的。 尽管Swift非常适合面向对象的编程,但是从for循环和String 文字的工作方式到标准库对泛型的强调,从本质上讲 ,Swift都是面向协议的。 Swift中有一句话:“不要从类开始,从协议开始”。 因此,让我们使用协议重做二进制搜索示例:
协议自我要求
一旦对协议有了自我需求,就会将协议转移到一个完全不同的世界,在该世界中,功能与类的重叠要少得多。
- 停止作为一种类型使用
- 集合变得同质而不是异质
- 实例之间的交互不再意味着所有模型类型之间的交互。
- 我们将动态多态性换成静态多态性,但是作为回报,我们为编译器提供了额外的类型信息,因此它更加可优化