I am experimenting some swift features.( Collection protocols). I would like to implement a structure that implements CollectionType. My code :
struct Book {
let id : String
let name : String
init(id: String, name: String) {
self.id = id
self.name = name
}
}
struct BookCollection {
var books : [Book]
}
First attempt :
extension BookCollection : CollectionType {
}
Compiler error : "Type BookCollection does not conform to the protocol Indexable"
Ok compiler let's conform to Indexable :
extension BookCollection : CollectionType {
var startIndex: Int {return 0}
var endIndex: Int {return books.count}
subscript(idx: Int) -> Book {
return books[idx]
}
}
The code is working now.
My Question is : if we forget the compiler errors, is there an easy way to know what functions/properties we should implement when conforming to a protocol in swift ? Thanks
PS : I don't want to read all the extensions to see if there are a default implementation or no, it's painful
The compiler errors will tell you. I put your code in a playground and saw the following errors
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>
Starting from the top, I see we need a type for the associated index type and then there is a whole load of errors that relate to it not being defined, so I add a typealias for protocol Indexable in the extension and that gives me a whole load more errors, so I change CollectionType to Indexable temporarily
extension BookCollection: Indexable
{
typealias Index = Int
}
And now i have the following:
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 is supposed to be an implementation detail (it starts with an underscore), but let's roll with it for now and add a type alias for it too.
extension BookCollection: Indexable
{
typealias Index = Int
typealias _Element = Book
}
Now I have the following
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 }
So now I implement the two properties and the subscript. I notice that implementing the subscript would allow the compiler to infer the two type alias types so I can delete those declarations.
extension BookCollection: Indexable
{
var startIndex: Int { return books.startIndex }
var endIndex: Int { return books.endIndex }
subscript(index: Int) -> Book
{
return books[index]
}
}
This gives no errors, so we change the protocol back to CollectionType and we still have no errors so we must be done.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With