Swift使用错误的相等函数来确定数组是否包含对象

时间:2017-03-01 19:49:08

标签: swift

我有一个符合Equatable的A类和一个继承自A的B类。我为每个类定义了==。

比较两个B对象时,使用正确的==函数来确定相等性。当检查B的数组是否包含对象B时,将调用为A定义的==。

//: Playground - noun: a place where people can play

class A: Equatable {
    var id: Int

    init(id: Int) {
        self.id = id
    }
}

class B: A {
}

func ==(lhs: A, rhs: A) -> Bool {
    print("Comparing using A's ==")
    return false
}


func ==(lhs: B, rhs: B) -> Bool {
    print("Comparing using B's ==")
    return lhs.id == rhs.id
}

let b1 = B(id: 1)
let b2 = B(id: 2)

let array: [B] = [b1, b2] // an array explicitly defined as containing B objects

print("\((b2 == b2))")
print("\(array.index(of: b2))")
print("\(array.contains(b2))")

输出:

Comparing using B's ==
true
Comparing using A's ==
Comparing using A's ==
nil
Comparing using A's ==
Comparing using A's ==
false

为什么会这样?

编辑:已解决!

正如 Hamish 在下面评论过,这是因为在某些情况下B会依赖A = =,更多信息,请参见第2点:== overload for custom class is not always called

为了解决这个问题,我做了以下工作:我定义了一个名为isEqualTo(object:)的方法,该方法是从A ==调用的。该方法被B覆盖。

由于经过另外几次方法调用的开销,这可能会有点效率低一些,但它对我正在处理的数据来说效果还不错。

//: Playground - noun: a place where people can play

class A: Equatable {
    var id: Int

    init(id: Int) {
        self.id = id
    }

    // define an isEqualTo method which takes another A instance
    // this will be called from A's ==
    func isEqualTo(object: A) -> Bool {
        return self == object
    }
}

class B: A {

    // override the isEqualTo: method
    override func isEqualTo(object: A) -> Bool {

        // if we are actually dealing with an object of type B, cast it 
        // first, then call B's ==
        if let bObject = object as? B {
            return self == bObject
        }

        // fallback to A's  ==
        return super.isEqualTo(object: object)
    }
}

func ==(lhs: A, rhs: A) -> Bool {
    print("Comparing using A's ==")
    // use a designated, overridable method to determine equality
    return lhs.isEqualTo(object: rhs)
}


func ==(lhs: B, rhs: B) -> Bool {
    print("Comparing using B's ==")
    return lhs.id == rhs.id
}

let b1 = B(id: 1)
let b2 = B(id: 2)

let array: [B] = [b1, b2]

print("\((b2 == b2))")
print("\(array.index(of: b2))")
print("\(array.contains(b2))")

输出:

Comparing using B's ==
true
Comparing using A's ==
Comparing using B's ==
Comparing using A's ==
Comparing using B's ==
Optional(1)
Comparing using A's ==
Comparing using B's ==
Comparing using A's ==
Comparing using B's ==
true

0 个答案:

没有答案