Как я могу предоставить по умолчанию протокол соответствия подписи только для типов классов? - PullRequest
1 голос
/ 23 октября 2019

Маркировка CacheManager с помощью 'class' решила мою проблему.

Вот случай: простой кэширующий , мутантное получение не то, что я хочу, так какчто делать для ссылочных типов или просто для типов классов?

protocol Cacher {
    associatedtype K
    associatedtype V
    subscript (key: K) -> V? {get set}
}

protocol MemoryCacher: Cacher {}

protocol FileCacher: Cacher {}

updated . добавить PrimayCacher |Дополнительные типы SecondaryCacher

protocol CacheManager {
    associatedtype Key
    associatedtype Value
    associatedtype PrimaryCacher: MemoryCacher where PrimaryCacher.K == Key, PrimaryCacher.V == Value
    associatedtype SecondaryCacher: FileCacher where SecondaryCacher.K == Key, SecondaryCacher.V == Value
    var primaryCacher: PrimaryCacher  { get set }
    var secondaryCacher: SecondaryCacher{ get set }
    subscript(key: Key) -> Value? { get set }
}

//try to provide a default subscript conformance, but actually not for the `mutating` get
extension CacheManager  {
    subscript(key: Key) -> Value? {
        mutating get {
            guard let result = primaryCacher[key] else {
                if let value = secondaryCacher?[key] {
                    primaryCacher[key] = value // the mutating is required for this
                    return value
                }
                return nil
            }
            return result
        }
        set {
            primaryCacher[key] = newValue
            secondaryCacher?[key] = newValue
        }
    }
}

1 Ответ

0 голосов
/ 23 октября 2019

Вам просто нужно добавить ограничение типа к AnyObject, которому соответствуют все классы.

extension CacherManager where Self: AnyObject {
    subscript(key: Key) -> Value? {
        get {
            guard let result = primaryCacher[key] else {
                if let value = secondaryCacher?[key] {
                    primaryCacher[key] = value // the mutating is required for this
                    return value
                }
                return nil
            }
            return result
        }
        set {
            primaryCacher[key] = newValue
            secondaryCacher?[key] = newValue
        }
    }
}

Мне также пришлось немного изменить объявление CacheManager для кода для компиляции и добавлениятребуемые методы протокола MemoryCacher и FileCacher, которые вы исключили из вопроса.

protocol Cacher {
    associatedtype K
    associatedtype V
    subscript (key: K) -> V? {get set}
}

class MemoryCacher<K, V>: Cacher {
    private var value: V?

    subscript(key: K) -> V? {
        get {
            return value
        }
        set {
            value = newValue
        }
    }
}

class FileCacher<K, V>: Cacher {
    private var value: V?

    subscript(key: K) -> V? {
        get {
            return value
        }
        set {
            value = newValue
        }
    }
}

protocol CacheManager {
    associatedtype Key
    associatedtype Value
    var primaryCacher: MemoryCacher<Key,Value> { get set }
    var secondaryCacher: FileCacher<Key,Value>? { get set }
    subscript(key: Key) -> Value? { get set }
}
...