[swift-users] odd `==` `!=` behavior with class that inherits `NSObject`
Nate Birkholz
nbirkholz at gmail.com
Tue Apr 18 22:31:17 CDT 2017
I'm not sure exactly how class declarations interact with the scope of a
do{ } statement. I declare a new static function inside your do{ } scope
and it works fine, but something about the mapping of `==` and `!=` to
`isEqual` in NSObject seems to be confused by the scope of the do{ } block.
I'm not sure what the use case is for declaring a class inside a do{ }
block, but it seems like a bug with SNObject operator mapping:
//: Playground - noun: a place where people can play
import UIKit
do{
class Foo:NSObject {
let name:String
init(name:String) {
self.name = name
}
public static func testStatic(_ object: Foo) {
print(object.name)
}
public static func ==(lhs: Foo, rhs: Foo) -> Bool {
guard type(of:lhs) == type(of:rhs) else { return false }
return lhs.name == rhs.name
}
public static func !=(lhs: Foo, rhs: Foo) -> Bool {
guard type(of:lhs) == type(of:rhs) else { return false }
return lhs.name != rhs.name
}
override func isEqual(_ object: Any?) -> Bool {
print("in isEqual")
guard let object = object as? Foo else { return false }
let _ = super.isEqual(object)
if self.name == object.name {
return true
}
return false
}
}
let a = Foo(name: "bar")
let b = Foo(name: "bar")
print(a == b) // true
print(a != b) // false
Foo.testStatic(a) // bar
}
output is:
in isEqual
true
in isEqual
false
bar
For the record, enclosing just the statements *outside* the class
declaration in a do{ } block works as expected:
class Foo:NSObject {
let name:String
init(name:String) {
self.name = name
}
public static func ==(lhs: Foo, rhs: Foo) -> Bool {
guard type(of:lhs) == type(of:rhs) else { return false }
return lhs.name == rhs.name
}
public static func !=(lhs: Foo, rhs: Foo) -> Bool {
guard type(of:lhs) == type(of:rhs) else { return false }
return lhs.name != rhs.name
}
override func isEqual(_ object: Any?) -> Bool {
print("in isEqual")
guard let object = object as? Foo else { return false }
let _ = super.isEqual(object)
if self.name == object.name {
return true
}
return false
}
}
do{
let a = Foo(name: "bar")
let b = Foo(name: "bar")
print(a == b) // true
print(a != b) // false
}
output:
true
false
On Tue, Apr 18, 2017 at 8:07 PM, Zhao Xin <owenzx at gmail.com> wrote:
> Just put your code in to a do-block. The result will be opposite.
>
>
> do {
>
>
>
> class Foo:NSObject {
>
> let name:String
>
>
>
> init(name:String) {
>
> self.name = name
>
> }
>
>
>
> public static func ==(lhs: Foo, rhs: Foo) -> Bool {
>
> guard type(of:lhs) == type(of:rhs) else { return false }
>
> return lhs.name == rhs.name
>
> }
>
>
>
> public static func !=(lhs: Foo, rhs: Foo) -> Bool {
>
> guard type(of:lhs) == type(of:rhs) else { return false }
>
> return lhs.name != rhs.name
>
> }
>
> }
>
>
>
> let a = Foo(name: "bar")
>
> let b = Foo(name: "bar")
>
>
>
> print(a == b) // true, now false
>
> print(a != b) // false, now true
>
> }
>
>
> Zhaoxin
>
> On Wed, Apr 19, 2017 at 11:04 AM, Nate Birkholz <nbirkholz at gmail.com>
> wrote:
>
>> Your issue seems to be that you created a custom implementation for the
>> `==` operator but not one for the `!=` operator. If I add a custom
>> implementation for `!=` I get the results you expected. Tthe default
>> implementation of NSObject's `isEqual` is a test for identity, like the
>> `===` in Swift. So when you ask "is `a` NOT the same object in memory as
>> `b`?" the object returns "true" because they are indeed not the same object.
>>
>> class Foo:NSObject {
>>
>> let name:String
>>
>>
>> init(name:String) {
>>
>> self.name = name
>>
>> }
>>
>>
>> public static func ==(lhs: Foo, rhs: Foo) -> Bool {
>>
>> guard type(of:lhs) == type(of:rhs) else { return false }
>>
>> return lhs.name == rhs.name
>>
>> }
>>
>>
>> public static func !=(lhs: Foo, rhs: Foo) -> Bool {
>>
>> guard type(of:lhs) == type(of:rhs) else { return false }
>>
>> return lhs.name != rhs.name
>>
>> }
>>
>> }
>>
>>
>> let a = Foo(name: "bar")
>>
>> let b = Foo(name: "bar")
>>
>>
>> print(a == b) // true
>>
>> print(a != b) // false
>>
>> On Tue, Apr 18, 2017 at 7:33 PM, Zhao Xin via swift-users <
>> swift-users at swift.org> wrote:
>>
>>> Sample 1: both `==` and `!=` is true.
>>>
>>> import Foundation
>>>
>>>
>>> class Foo:NSObject {
>>>
>>> let name:String
>>>
>>>
>>> init(name:String) {
>>>
>>> self.name = name
>>>
>>> }
>>>
>>>
>>> public static func ==(lhs: Foo, rhs: Foo) -> Bool {
>>>
>>> guard type(of:lhs) == type(of:rhs) else { return false }
>>>
>>> return lhs.name == rhs.name
>>>
>>> }
>>>
>>> }
>>>
>>>
>>> let a = Foo(name: "bar")
>>>
>>> let b = Foo(name: "bar")
>>>
>>>
>>> print(a == b) // true
>>>
>>> print(a != b) // true
>>>
>>> Sample 2: Add above code to a do-block, behavior changes to expect
>>>
>>> do {
>>>
>>> class Foo:NSObject {
>>>
>>> let name:String
>>>
>>>
>>>
>>> init(name:String) {
>>>
>>> self.name = name
>>>
>>> }
>>>
>>>
>>>
>>> public static func ==(lhs: Foo, rhs: Foo) -> Bool {
>>>
>>> guard type(of:lhs) == type(of:rhs) else { return false }
>>>
>>> return lhs.name == rhs.name
>>>
>>> }
>>>
>>> }
>>>
>>>
>>>
>>> let a = Foo(name: "bar")
>>>
>>> let b = Foo(name: "bar")
>>>
>>>
>>>
>>> print(a == b) // false
>>>
>>> print(a != b) // true
>>>
>>> }
>>>
>>> Sample 3: A little investigation shows that `==` didn't call NSObject's `
>>> func isEqual(_ object: Any?) -> Bool` but `!=` did.
>>>
>>> class Foo:NSObject {
>>>
>>> let name:String
>>>
>>>
>>>
>>> init(name:String) {
>>>
>>> self.name = name
>>>
>>> }
>>>
>>>
>>>
>>> public static func ==(lhs: Foo, rhs: Foo) -> Bool {
>>>
>>> guard type(of:lhs) == type(of:rhs) else { return false }
>>>
>>> return lhs.name == rhs.name
>>>
>>> }
>>>
>>>
>>>
>>> override func isEqual(to object: Any?) -> Bool {
>>>
>>> print("111")
>>>
>>> return super.isEqual(to: object)
>>>
>>> }
>>>
>>>
>>>
>>> override func isEqual(_ object: Any?) -> Bool {
>>>
>>> print("2222")
>>>
>>> return super.isEqual(object)
>>>
>>> }
>>>
>>> }
>>>
>>>
>>> let a = Foo(name: "bar")
>>>
>>> let b = Foo(name: "bar")
>>>
>>>
>>> print(a == b) // true
>>>
>>> print(a != b) // 2222, true
>>>
>>> print(!(a == b)) // false
>>>
>>>
>>> So I am wondering what is the future? Will we keep on using `isEqual(_
>>> object: Any?)` with class that inherits `NSObject`, or we are trying
>>> to drop it?
>>>
>>> Xcode 8.3.1 (8E1000a), 3.1 (swiftlang-802.0.51 clang-802.0.41), macOS 10.12.4
>>> (16E195)
>>>
>>> Zhaoxin
>>>
>>> _______________________________________________
>>> swift-users mailing list
>>> swift-users at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-users
>>>
>>>
>>
>>
>> --
>> Nate Birkholz
>>
>
>
--
Nate Birkholz
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20170418/4436804d/attachment.html>
More information about the swift-users
mailing list