Edward Ashak
Edward Ashak

Reputation: 2421

Extending CollectionType in Swift 2

So i'm trying to extend the CollectionType protocol in Swift 2

protocol CollectionAccess: CollectionType {
    func getElement<T: Hashable>(key: T) -> Self.Generator.Element?
}

extension Dictionary : CollectionAccess {
    func getElement(key: Key) -> Dictionary.Element? {
        if let value = self[key] {
            return (key, value)
        }
        return nil
    }
}

When it compiles it throws an error that :

error: type 'Dictionary' does not conform to protocol 'CollectionAccess' extension Dictionary : CollectionAccess

the function getElement(...) compiles fine and works fine as a n extension of Dictionary by itself BUT not as

extension Dictionary : CollectionAccess

=====progress======================

i managed to get rid of the error by changing my signature in the Dictionary extension:

extension Dictionary : CollectionAccess {
    func getElement<K: Hashable where K == Dictionary.Key>(key: K) -> Dictionary.Generator.Element? {
        self[key]

Now the issue is:

error: cannot subscript a value of type 'Dictionary' with an index of type 'K' self[key]

What I'm going for is setting up the signature to say the K is the same Hashable as the Dictionary.Key type is.

Upvotes: 1

Views: 793

Answers (2)

Qbyte
Qbyte

Reputation: 13243

If it is possible to change the declaration of your protocol you can also solve this by making an associated type requirement:

protocol CollectionAccess: CollectionType {
    typealias T = Hashable
    func getElement(key: T) -> Self.Generator.Element?
}

Now your dictionary implementation works as expected without modification.

(But now you cannot create arrays of type [CollectionAccess] (only as parameter in a generic function where is has to be "homogeneous"))

Upvotes: 1

James Alvarez
James Alvarez

Reputation: 7219

'Key' and 'Value' are placeholders in Dictionary, so you can't access these in the method signature for a CollectionType protocol extension - so to get this to work you have to do a cast.

It seems slightly wrong to me, but I think you can just about get it to work with something like this:

extension Dictionary : CollectionAccess {
    func getElement<T : Hashable>(key: T) -> Dictionary.Generator.Element?     {
        if key.self is Key.Type {
            let tKey = key as! Key
            if let value = self[tKey] {
                return (tKey, value)
            }
         }
        return nil
    }
}

The thing is, CollectionType doesn't have a placeholder that corresponds to Dictionary's 'Key' placeholder. Not all CollectionType's consist of key value pairs, so therefore it doesn't make sense to make CollectionType have a Key / Value type method. For example another CollectionType is Array - what would getElement return for an array?

Upvotes: 2

Related Questions