协议符合

时间:2016-01-12 15:42:14

标签: swift swift2

我正在试验一些快速的功能。(收集协议)。我想实现一个实现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]
}

首次尝试:

extension BookCollection : CollectionType {
}

编译器错误:“类型BookCollection不符合协议可索引”

好的编译器让我们符合Indexable:

extension BookCollection : CollectionType {
    var startIndex: Int {return 0}
    var endIndex: Int {return books.count}

    subscript(idx: Int) -> Book {
        return books[idx]
    }
}

代码现在正在运行。

我的问题是:如果我们忘记编译器错误,是否有一种简单的方法可以知道在符合swift协议时我们应该实现哪些功能/属性? 谢谢

PS:我不想阅读所有扩展程序以查看是否存在默认实现,否则很痛苦

2 个答案:

答案 0 :(得分:1)

编译器错误会告诉你。我把你的代码放在游乐场,看到了以下错误

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>

从顶部开始,我看到我们需要一个关联索引类型的类型,然后有一大堆错误与它没有被定义相关,所以我在协议中添加了typealias协议扩展,这会给我带来更多错误,因此我暂时将CollectionType更改为Indexable

extension BookCollection: Indexable
{
    typealias Index = Int
}

现在我有以下内容:

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
              ^

_Element应该是一个实现细节(它以下划线开头),但现在让它滚动它并为它添加一个类型别名。

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,我们仍然没有错误,所以我们必须完成。

答案 1 :(得分:0)

除了使用编译器错误之外,没有简单的方法。为什么?因为协议支持默认实现,并且您无法知道哪些协议函数具有默认实现(除了编译器不抱怨它们)。

例如,SequenceType定义了许多功能。你实现了它们吗?不,因为大多数都有默认实现。唯一需要的是func generate() -> GeneratorType和相关的GeneratorType。之后,您的子类型SequenceType已完成 - 您可能会选择覆盖某些默认实现,但不需要。 CollectionTypeIndexableGeneratorType默认为IndexingGenerator<Self>

当然,如果您有源代码,那么您可以识别默认协议实现,但是当您完成此操作时,您也可以让编译器告诉您。或者,Apple文档确实列出了一些带有“默认实现”的功能,这可能表明不需要实现的功能。或者,如评论中所述,swiftdoc.org以清晰的形式标识所需的类型/功能。