Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 符合协议_Swift_Swift2 - Fatal编程技术网

Swift 符合协议

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] }

我正在试验一些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]
}
第一次尝试:

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]
    }
}