我的模特课:
func ==(lhs: Tracking,rhs: Tracking) -> Bool {
    // This method never executes if called from BaseCache
    return lhs.id == rhs.id 
}
class Tracking: NSObject,Equatable,Printable {
    var id: String?
    ..... 
} 
 类,使用泛型类型:
class BaseCache<T: NSObject where T: Equatable,T: Printable>  {
    .....
    func removeEntities(entities: [T]) {
        var indexesToRemove = [Int]()
        for i in 0...allEntities.count - 1 {
            let item = allEntities[i]
            for entity in entities {
                println("equal: \(entity == item)")
                // FOR SOME REASONS THE STATEMENT BELOW IS ALWAYS FALSE
                if entity == item {
                    indexesToRemove.append(i)
                    break
                }
            }
        }
        for index in indexesToRemove {
            allEntities.removeAtIndex(index)
        }
        didRemoveEntities()
    }
} 
 它的子类:
class TrackingCache<T: Tracking>: BaseCache<Tracking> {
} 
 当我调用TrackingCache实例的removeEntities方法时,我总是在输出中得到相等的:false,即使id是相同的.
但是,如果我直接将方法移动到TrackingCache类,它似乎工作正常!
任何想法为什么会发生这种情况以及如何解决这个问题?
解决方法
请考虑以下代码:
class C: NSObject,Equatable {
    let id: Int
    init(_ id: Int) { self.id = id }
}
// define equality as IDs are equal
func ==(lhs: C,rhs: C) -> Bool {
    return lhs.id == rhs.id 
}
// create two objects with the same ID
let c1 = C(1)
let c2 = C(1)
// true,as expected
c1 == c2 
 好的,现在创建两个NSObject类型的变量,并为它们分配相同的值:
let o1: NSObject = c1 let o2: NSObject = c2 // this will be false o1 == o2
为什么?因为你正在调用函数func ==(lhs:NSObject,rhs:NSObject) – > Bool,不是func ==(lhs:C,rhs:C) – >布尔.根据o1和o2所指的内容,在运行时不会动态确定要选择哪个重载函数.它是由Swift在编译时根据o1和o2的类型确定的,在这种情况下是oSObject.
NSObject ==的实现与你的equals不同 – 它调用lhs.isEqual(rhs),如果不覆盖检查引用相等(即两个引用指向同一个对象),它会回退.他们不是,所以他们不平等.
为什么在BaseCache中会发生这种情况,而在TrackingCache中却没有?因为BaseCache被定义为仅限制为NSObject,所以T只具有NSObject的功能 – 类似于将c1分配给NSObject类型的变量时,将调用==的NSObject版本.
另一方面,TrackingCache保证T至少是一个Tracking对象,因此使用了跟踪的==版本. Swift会选择所有可能重载的“特定” – 跟踪比它的基类NSObject更具体.
这是一个更简单的例子,只是通用函数:
func f<T: NSObject>(lhs: T,rhs: T) -> Bool {
    return lhs == rhs
}
func g<T: C>(lhs: T,rhs: T) -> Bool {
    return lhs == rhs
}
f(c1,c2) // false
g(c1,c2) // true 
 如果要解决此问题,可以覆盖isEqual:
class C: NSObject,Equatable {
    ...
    override func isEqual(object: AnyObject?) -> Bool {
        return (object as? C)?.id == id
    }
}
// this is Now true:
o1 == o2
// as is this:
f(c1,c2) 
 这种技术(具有==调用动态调度的类方法)也是一种为非NSObject类实现此行为的方法.当然,结构没有这个问题,因为它们不支持继承 – 结构得分为1!