Ios 均衡实现不需要';我似乎无法使用泛型

Ios 均衡实现不需要';我似乎无法使用泛型,ios,generics,swift,Ios,Generics,Swift,我仍在与迅捷的仿制药抗争。今天我发现我的Equatable协议的实现不起作用,如果它是从泛型类调用的 我的模型课: func ==(lhs: Tracking, rhs: Tracking) -> Bool { // This method never executes if called from BaseCache return lhs.id == rhs.id } class Tracking: NSObject, Equatable, Printable {

我仍在与迅捷的仿制药抗争。今天我发现我的Equatable协议的实现不起作用,如果它是从泛型类调用的

我的模型课:

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()
    }
}
类基本缓存{
.....
功能删除实体(实体:[T]){
var indexesToRemove=[Int]()
对于0…allenties.count-1中的i{
let item=allenties[i]
对于实体中的实体{
println(“相等:\(实体==项目)”)
//由于某些原因,下面的陈述总是错误的
如果实体==项目{
indexesToRemove.append(i)
打破
}
}
}
对于IndexStoreMove中的索引{
Allenties.removeAtIndex(索引)
}
didremoventies()
}
}
它是一个子类:

class TrackingCache<T: Tracking>: BaseCache<Tracking> {
}
class TrackingCache:BaseCache{
}
当我调用
TrackingCache
实例的
removeenties
方法时,我总是在输出中得到
equal:false
,即使
id
s是相同的

但是如果我直接将该方法移动到
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)->Bool
。选择哪个重载函数在运行时不会根据
o1
o2
所指内容动态确定。它是由Swift在编译时根据
o1
o2
的类型确定的,在这种情况下是
NSObject

NSObject
=
的实现方式与您的equals不同–它调用
lhs.isEqual(rhs)
,如果不重写,它会返回到检查引用相等性(即两个引用指向同一个对象)。他们不是,所以他们不平等

为什么使用
BaseCache
时会发生这种情况,而使用
TrackingCache
时不会发生这种情况?由于
BaseCache
被定义为仅约束
NSObject
,因此
T
仅具有
NSObject
的功能–类似于将
c1
分配给
NSObject
类型的变量时,将调用
NSObject
版本的
=/code>

另一方面,
TrackingCache
保证
T
将至少是一个
跟踪
对象,因此使用用于跟踪的
=
版本。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

这种技术(让
==
调用动态调度的类方法)也是为非NSObject类实现这种行为的一种方法。当然,结构没有这个问题,因为它们不支持继承——结构得1分

顺便说一句,您可以为0中的i编写
,而不是
…allenties.count-1
您可以为0中的i编写
。根据
allenties
是什么,您也可以为allenties
中的项指定
。不过,他需要一个索引,以便稍后进行删除
中的(idx,item)代码>会起作用-它依赖于
Int
索引,但这里就是这种情况。@空速性能感谢您的建议,但它似乎
包含
使用
均衡
实现,这不会起作用,对吗?@AndreyGordeev根据我的回答,如果您实现equalable以使用
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)