具有约束的关联类型的协议不允许将协议类型用作该关联类型

时间:2019-11-24 08:56:25

标签: swift generics protocols

我有一个Observable协议:

/**
Conforming types gain the ability to add/remove observers, and send notifications to them.
*/
protocol Observable: AnyObject {
    associatedtype ObserverType
    var observers: [ObserverType] { get set }
}

该功能包含在扩展程序中:

extension Observable {
    func addObserver(_ o: ObserverType) {
        self.observers.append(o)
    }

    func removeObserver(_ o: ObserverType) {
        // ...
    }

    /**
     This is how you indicate which notification you wish to send.
     This method takes in a block, which will receive your ObserverType.
     Here you can call the particular method you want on the observer.
     The block will be applied to all observers.
     */
    func notify(_ block: (ObserverType) -> ()) {
        for each in self.observers {
            block(each)
        }
    }
}

这种设计的思想是,当一个对象被认为是有趣的时,我们将其制成Observable,并将我们想要的每个通知作为方法放入协议中,并声明作为您的ObserverType。您不能添加不符合该协议的观察者。

因此,假设我有一个名为Profile的模型类。我将想要的通知放入协议:

protocol ProfileObserver {
    func didReceiveImage(image: UIImage)
}

现在,我将使Profile符合Observable

class Profile: Observable {
    typealias ObserverType = ProfileObserver
    var observers: [ProfileObserver] = []

    /**
    Just to demonstrate how you would send a particular notification to your observers.
    */
    func foo() {
        self.notify { (observer) in
            observer.didReceiveImage(image: someImage)
        }
    }
}

一切正常。当我想向ObserverType添加约束时会出现问题。 我想添加ObserverType协议中的AnyObject符合Observable的约束条件:

associatedtype ObserverType: AnyObject

这是因为我想在removeObserver方法中使用===运算符:

func removeObserver(_ o: ObserverType) {
    let i = self.observers.firstIndex { $0 === o }
    precondition(i != nil, "Attempted to remove an observer that wasn't even added")
    self.observers.remove(at: i!)
}

但是编译器抱怨Profile不符合Observable,即使我使ProfileObserver符合AnyObject也是如此。

似乎为关联类型添加了约束,从而消除了为ObserverType使用协议类型的能力。

例如,如果我制定了一些Foo协议,并设定了约束条件:

associatedtype ObserverType: Foo

我不能使用符合Foo的协议作为我的ObserverType;它只会让我使用非协议类型,例如符合Foo的结构或类。

0 个答案:

没有答案