Swift 符合协议
我正在试验一些swift功能(收集协议)。我想实现一个实现CollectionType的结构。我的代码:Swift 符合协议,swift,swift2,Swift,Swift2,我正在试验一些swift功能(收集协议)。我想实现一个实现CollectionType的结构。我的代码: struct Book { let id : String let name : String init(id: String, name: String) { self.id = id self.name = name } } struct BookCollection { var books : [Book] }
struct Book {
let id : String
let name : String
init(id: String, name: String) {
self.id = id
self.name = name
}
}
struct BookCollection {
var books : [Book]
}
第一次尝试:
extension BookCollection : CollectionType {
}
编译器错误:“类型BookCollection不符合可索引协议”
好的,让我们遵循可转位:
extension BookCollection : CollectionType {
var startIndex: Int {return 0}
var endIndex: Int {return books.count}
subscript(idx: Int) -> Book {
return books[idx]
}
}
代码正在运行
我的问题是:如果我们忘记了编译器错误,有没有一种简单的方法可以知道在遵守swift协议时应该实现哪些函数/属性?谢谢
PS:我不想阅读所有的扩展来查看是否有默认实现,这很痛苦除了使用编译器错误之外,没有其他简单的方法。为什么?因为协议支持默认实现,而您不知道哪些协议函数具有默认实现(除非编译器没有对此进行抱怨) 例如,
SequenceType
定义了许多函数。你们都实现了吗?不,因为大多数都有默认实现。只需要func generate()->GeneratorType
和相关的GeneratorType
。然后,您的子类型SequenceType
就完成了-您可以选择覆盖一些默认实现,但不需要。对于CollectionType
而言,它是可索引的
(并且GeneratorType
默认为索引生成器
)
当然,如果您有源代码,那么您可以确定默认的协议实现,但是,在您这样做之前,您最好让编译器告诉您。或者,苹果的文档中确实列出了一些带有“默认实现”的功能,这些功能可能表示不需要实现的功能。或者,如注释中所述,swiftdoc.org以清晰的形式标识所需的类型/函数。编译器错误会告诉您。我把你的代码放在操场上,发现了以下错误
Playground execution failed: MyPlayground.playground:15:1: error: type 'BookCollection' does not conform to protocol 'Indexable'
extension BookCollection: CollectionType
^
Swift.Indexable:6:15: note: unable to infer associated type 'Index' for protocol 'Indexable'
typealias Index : ForwardIndexType
^
Swift.CollectionType:2:12: note: inferred type 'Range<BookCollection.Index>' (by matching requirement 'subscript') is invalid: does not conform to 'ForwardIndexType'
public subscript (bounds: Range<Self.Index>) -> Slice<Self> { get }
^
MyPlayground.playground:15:1: error: type 'BookCollection' does not conform to protocol 'SequenceType'
extension BookCollection: CollectionType
^
Swift.SequenceType:35:17: note: protocol requires function 'generate()' with type '() -> Generator'
public func generate() -> Self.Generator
^
Swift.SequenceType:2:17: note: candidate has non-matching type '<`Self`> () -> `Self`' (aka '<τ_0_0> () -> τ_0_0')
public func generate() -> Self
^
Swift.SequenceType:5:17: note: candidate has non-matching type '<`Self`> () -> `Self`.Base.Generator' (aka '<τ_0_0> () -> τ_0_0.Base.Generator')
public func generate() -> Self.Generator
^
Swift.CollectionType:2:17: note: candidate has non-matching type '<`Self`> () -> IndexingGenerator<`Self`>' (aka '<τ_0_0> () -> IndexingGenerator<τ_0_0>')
public func generate() -> IndexingGenerator<Self>
现在我有以下几点:
Playground execution failed: MyPlayground.playground:15:1: error: type 'BookCollection' does not conform to protocol 'Indexable'
extension BookCollection: Indexable
^
Swift.Indexable:21:15: note: protocol requires nested type '_Element'
typealias _Element
^
\u元素
应该是一个实现细节(它以下划线开头),但现在让我们继续使用它,并为它添加一个类型别名
extension BookCollection: Indexable
{
typealias Index = Int
typealias _Element = Book
}
现在我有以下几点
Playground execution failed: MyPlayground.playground:15:1: error: type 'BookCollection' does not conform to protocol 'Indexable'
extension BookCollection: Indexable
^
Swift.Indexable:12:16: note: protocol requires property 'startIndex' with type 'Index' (aka 'Int')
public var startIndex: Self.Index { get }
^
Swift.Indexable:20:16: note: protocol requires property 'endIndex' with type 'Index' (aka 'Int')
public var endIndex: Self.Index { get }
^
Swift.Indexable:22:12: note: protocol requires subscript with type 'Index -> _Element'
public subscript (position: Self.Index) -> Self._Element { get }
现在我实现了这两个属性和下标。我注意到,实现下标将允许编译器推断两种类型别名类型,以便删除这些声明
extension BookCollection: Indexable
{
var startIndex: Int { return books.startIndex }
var endIndex: Int { return books.endIndex }
subscript(index: Int) -> Book
{
return books[index]
}
}
这不会产生错误,因此我们将协议更改回
CollectionType
,但仍然没有错误,因此必须执行此操作。命令+单击CollectionType
将带您进入协议。任何非可选的
都应该实现。什么是“任何非可选的”?在协议定义中,一些被标记为@optional
。这意味着,无论哪个类想要符合该协议,都可以实现或不实现该函数。任何函数或属性如果在实现之前没有@optional
,则必须将其实现,以避免您的代码产生任何编译器错误。(a)没有那么痛苦,参考文档应该在您拥有的地方提供。(b) 你真的需要一些专门类型的藏书吗?首先回答这个问题是最重要的。您希望在那里实现哪些特殊功能?@hannad您在哪里看到“@optional”关键字?我想我可以补充一点,即使不看源代码,swiftdoc.org也可以很好地概述哪些方法或属性是在符合协议时必须提供的实现。在上面的示例中,您清楚地告诉我们协议一致性只需要函数generate()
(注意,不是generator()
)即可。@dfri func generate()->IndexingGenerator有默认实现:-)(是的,它是必需的,但也实现了…)谢谢您的回答。我觉得这个方法很痛苦。我希望在Swift的未来版本中使用另一种方法(如Objective C中的@optional关键字)。我花了大约5分钟的时间完成了所有这些。可选注释(确实存在)的问题是,某些非可选方法具有默认实现,CollectionType就是这种情况。有很多非可选方法,但如果实现可索引的
,则不必实现它们。
extension BookCollection: Indexable
{
var startIndex: Int { return books.startIndex }
var endIndex: Int { return books.endIndex }
subscript(index: Int) -> Book
{
return books[index]
}
}