Разница между использованием ObjectIdentifier() и оператора ===
Допустим, я реализую корневой класс в Swift, который я объявляю, принимает Equatable
протокол (я хочу иметь возможность сказать, содержит ли массив моего типа данный экземпляр или нет).
Какая разница - если есть, в данном конкретном случае - между реализацией протокола требуется ==
оператор как:
public static func ==(lhs: MyClass, rhs: MyClass) -> Bool {
return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
}
... в отличие от просто сделать это:
public static func ==(lhs: MyClass, rhs: MyClass) -> Bool {
return (lhs === rhs)
}
В качестве ссылки, это то, что говорится в документации ObjectIdentifier()
:
Уникальный идентификатор экземпляра класса или метатипа. В Swift только экземпляры классов и метатипы имеют уникальные идентификаторы. Не существует понятия идентичности для структур, перечислений, функций или кортежей.
... и это то, что в разделе "Основные операторы" языка программирования Swift (Swift 3) говорится о ===
оператор:
НОТА
Swift также предоставляет два идентификатора оператора (
===
а также!==
), который вы используете, чтобы проверить, ссылаются ли обе ссылки на один и тот же экземпляр объекта. Для получения дополнительной информации см. Классы и структуры.
1 ответ
Для экземпляра класса нет никакой разницы, см. Следующие комментарии в ObjectIdentifier.swift:
/// Creates an instance that uniquely identifies the given class instance.
///
/// The following example creates an example class `A` and compares instances
/// of the class using their object identifiers and the identical-to
/// operator (`===`):
///
/// class IntegerRef {
/// let value: Int
/// init(_ value: Int) {
/// self.value = value
/// }
/// }
///
/// let x = IntegerRef(10)
/// let y = x
///
/// print(ObjectIdentifier(x) == ObjectIdentifier(y))
/// // Prints "true"
/// print(x === y)
/// // Prints "true"
///
/// let z = IntegerRef(10)
/// print(ObjectIdentifier(x) == ObjectIdentifier(z))
/// // Prints "false"
/// print(x === z)
/// // Prints "false"
///
Это также становится очевидным из реализации ==
за ObjectIdentifier
, который просто сравнивает указатели с хранилищем объекта:
public static func == (x: ObjectIdentifier, y: ObjectIdentifier) -> Bool {
return Bool(Builtin.cmp_eq_RawPointer(x._value, y._value))
}
что то, что ===
Оператор также делает:
public func === (lhs: AnyObject?, rhs: AnyObject?) -> Bool {
switch (lhs, rhs) {
case let (l?, r?):
return Bool(Builtin.cmp_eq_RawPointer(
Builtin.bridgeToRawPointer(Builtin.castToUnknownObject(l)),
Builtin.bridgeToRawPointer(Builtin.castToUnknownObject(r))
))
case (nil, nil):
return true
default:
return false
}
}
ObjectIdentifier
соответствует Hashable
, так что это полезно, если вы хотите реализовать этот протокол для вашего класса:
extension MyClass: Hashable {
var hashValue: Int {
return ObjectIdentifier(self).hashValue
}
}
Идентификатор объекта также может быть создан для мета-типов (например, ObjectIdentifier(Float.self)
) для которого ===
не определено.