Search code examples
swiftgenericsswift-extensionsswift-protocols

Swift generics in protocol: operator '===' cannot be applied to operands of type '_' and 'Self.T'


I'm trying to build a simple observer mixin with Swift 2. Here comes just the relevant part.

protocol Observable{

    typealias T 
    var observers:[T] { get set }
    mutating func removeObserver(observer:T)
}

To create the mixin I use an extension:

extension Observable{

    mutating func removeObserver(observer:T){
        let index = self.observers.indexOf{ $0 === observer }
        if let _ = index{
            self.observers.removeAtIndex(index)
        }
    }   
}

This creates the compiler error: Binary operator '===' cannot be applied to operands of type '_' and 'Self.T'

Can you explain to me why this error is occurring?


Solution

  • The "identical-to" operator === can only be applied to reference types, i.e. instances of a class. One possible solution is to restrict the generic type T to AnyObject (the protocol to which all classes implicitly conform):

    protocol Observable {
    
        typealias T : AnyObject
        var observers:[T] { get set }
        mutating func removeObserver(observer:T)
    }
    
    extension Observable {
    
         mutating func removeObserver(observer:T) { 
            if let index = (self.observers.indexOf { $0 === observer }) {
                self.observers.removeAtIndex(index)
            }
        }   
    }
    

    Alternatively, restrict T to Equatable types (which means that a == operator must be defined for the type):

    protocol Observable {
    
        typealias T : Equatable
        var observers:[T] { get set }
        mutating func removeObserver(observer:T)
    }
    
    extension Observable {
    
         mutating func removeObserver(observer:T) { 
            if let index = self.observers.indexOf(observer) {
                self.observers.removeAtIndex(index)
            }
        }   
    }