在设计的API,我碰上这种在每一个角落:为什么使用Self或associatedtype对协议进行限制?
协议只能作为一种通用的约束,因为它具有自我或associatedType要求
这是什么意思是,你基本上可以在协议级别不使用Self
或associatedtype
(如果您打算自行使用协议类型),否则需要通用的类型自身级联失控。
这很烦人(阅读:使得它几乎不可能设计合理的API,例如暴露协议但隐藏实现)。举例来说,你不能有一个简单的数据容器协议:
protocol DataContainer: Equatable {
var id: Int { get }
var content: Data { get }
}
问题是Equatable
需要静态函数==
这是当然,使用Self
表示。因此,您不能拥有类似[DataContainer]
或任何其他自然事物。我首先遇到了用户组(阵列)(可能是三种不同类型之一)。
“官方”推荐的“解决方案”是使委托/包装结构消除类型变量,如AnyDataContainer
。这感觉就像一个相当愚蠢,拙劣的解决方法,而不是适当的API设计。
我真的不明白为什么类型系统有这个限制。原因是什么?为什么编译器无法为每个协议P
创建AnyP
来解决它?
我相信[我对前一个问题的回答](https://stackoverflow.com/a/41698579/2976878)基本上回答了这个问题 - 没有真正的原因,为什么这是不可能的,Swift只是没有还支持它。引用我在我的答案中引用的泛型声明“*对存在类型的限制来自实现限制,但即使协议具有自约束或关联类型,也允许协议类型的值是合理的。*“ – Hamish
@Hamish我已经忘记了这一点,谢谢,不过我想知道是否还有其他问题,比如说,”我们“所有的东西都可以静态解决吗?有很多工具可以动态地处理类型*因此在这里可能会有一些真正的(或者至少是次要的)限制。例如,我没有看到编译器如何使用'Self'调用一个函数来正常工作不知道'Self'会解决什么问题,因为它基本上都想静态分派。 – Raphael
如果需求有相关类型或'Self'需求(例如你的例子中的'=='),以便在类型为协议的实例上使用它们(当支持这种情况时),你确实需要给编译器一些具体的类型信息。在[“开放存在”一节中详细介绍了这种处理的一种方式](https ://github.com/apple/swift/blob/master/docs /GenericsManifesto.md#opening-existentials)泛型声明。 – Hamish