gpt4 book ai didi

ios - Equatable 实现似乎不适用于泛型

转载 作者:搜寻专家 更新时间:2023-10-30 22:06:35 24 4
gpt4 key购买 nike

我仍在与 Swift 泛型作斗争。今天我发现如果从泛型类调用我的 Equatable 协议(protocol)实现不起作用。

我的模型类:

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 方法时,我总是在输出中得到 equal: 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

OK 现在创建两个 NSObject 类型的变量,并为它们分配相同的值:

let o1: NSObject = c1
let o2: NSObject = c2

// this will be false
o1 == o2

为什么?因为你正在调用函数 func ==(lhs: NSObject, rhs: NSObject) -> Boolnot func ==(lhs: C, rhs: C) -> bool 。选择哪个重载函数不是在运行时根据o1o2 引用动态确定的。它由 Swift 在编译时根据 o1o2 的类型确定,在本例中为 NSObject

NSObject == 的实现方式与您的 equals 不同——它调用 lhs.isEqual(rhs),如果没有被重写则回退到检查引用相等性(即两个引用是否指向同一个对象)。它们不是,所以它们不相等。

为什么 BaseCache 会发生这种情况,而 TrackingCache 不会?因为 BaseCache 被定义为只限制于 NSObject,所以 T 只有 NSObject 的能力——类似于当您将 c1 分配给 NSObject 类型的变量时,将调用 ==NSObject 版本。

TrackingCache 另一方面保证 T 至少是一个 Tracking 对象,所以 ==用于跟踪。 Swift 会从所有可能的重载中选择更“具体”的——Tracking 比它的基类 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!

关于ios - Equatable 实现似乎不适用于泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27815675/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com