Alex Popov
Alex Popov

Reputation: 2519

Passing self as argument to a Protocol function that wants same type as self as the argument

I'm writing an async dictionary that returns a Future with the value:

The dictionary inside my class is generic, so the class is as well. Currently the user has to read the docs and know to set the dataCall function, which is how the dictionary knows how to get a value for a key, in the form

var dataCall: ((key: Key) -> Future<Value, MyError>)?

But this requires other programmers to know about the data call and set it. So I wrote a protocol

protocol CacheDelegate {
    typealias T: Hashable
    typealias U
    func dataCallForCacheManager(cacheManager: CacheManager<T, U>) → (key: T) → Future<Value, MyError>
}

However, then if I try and call this in init() as

delegate.dataCallForCacheManager(self)

I get the error

Cannot invoke dataCallForDictionary with an argument list of type '(CacheManager)'

I also cannot make a var delegate: CacheDelegate? because

Protocol CacheDelegate can only be used as a generic constraint because it has Self or associated type requirements.

So I find myself in a pickle where I can't pass myself as an argument, and I can't set a delegate to get my data call from this protocol. Am I missing something? I'm willing to do Swift 2 Voodoo.

The contents of a toy example (without Futures and the dictionary and everything) is below:

import Foundation

protocol Delegate {
    typealias T: Hashable
    typealias U
    func dataCallForDictionary(dictionary: MyDictionary<T, U>) -> (T) -> (U)
}

struct MyDictionary<Key: Hashable, Value> {
    typealias T = Key
    typealias U = Value

    init<Object: Delegate>(delegate: Object) {
        dataCall = delegate.dataCallForDictionary(self)
//        self.delegate = delegate
    }

    var delegate: Delegate?

    var dataCall: ((key: Key) -> Value)?
}

Upvotes: 1

Views: 1118

Answers (2)

San Gyeol Kang
San Gyeol Kang

Reputation: 110

I think delegate in MyDictionary struct should be weak.

Upvotes: 0

ABakerSmith
ABakerSmith

Reputation: 22939

Taking your example, have you considered doing:

protocol Delegate {
    func dataCallForDictionary<T: Hashable, U>(dictionary: MyDictionary<T, U>) -> T -> U
}

struct MyDictionary<Key: Hashable, Value> {
    var delegate: Delegate?
    var dataCall: ((key: Key) -> Value)?

    init(delegate: Delegate) {
        self.delegate = delegate
        dataCall = delegate.dataCallForDictionary(self)
    }
}

Upvotes: 1

Related Questions