使用要求带有 Self 或关联类型的协议

2020-03-02 英文原文

在 Swift 语言中,协议可以被用作类型,作为泛型约束,又或是不透明类型的一部分:

// CustomStringConvertible 可以被用作一个类型,
func foo(bar: CustomStringConvertible) { /* ... */ }

// ……或作为对泛型 'T' 的约束,
func bar<T: CustomStringConvertible>(baz: T) { /* ... */ }

// ……或作为不透明类型的一部分。
func baz() -> some CustomStringConvertible { /* ... */ }

虽然 Swift 中所有的协议都可以被用作泛型约束以及不透明类型的一部分,但并不是所有的协议都能被用作类型。准确地说,如果一个协议的要求中使用了 Self 或者关联类型,那么它就不能被作为类型使用。Identifiable 就是这样的一个例子:其 var id: ID { get } 这个要求使用了关联类型 ID。因此,下面这段代码是无法编译的:

func foo(bar: Identifiable) { /* ... */ }
// error: protocol 'Identifiable' can only be used as a generic constraint because it has Self or associated type requirements

之所以像 Identifiable 这样要求使用 Self 或者关联类型的协议不能被用作类型,是因为那样的类型实际上一般并没有什么用处。对于 var id: ID { get } 这样有 Self 或者关联类型的要求,既然我们并不知道其中的关联类型具体是什么,那自然也就无法使用。

在处理被 Self 或者关联类型要求约束的泛型协议时,使用不透明类型或者自己实现类型擦除能解决大多数的问题。欲知详情,请参阅《The Swift Programming Language》中 协议泛型不透明类型 这些章节。

许可协议:Apache 2.0 许可+运行时特许

属性包装器的实现要求

comments powered by Disqus