В swift есть два оператора равенства: double равно (==
), а тройка равна ( ===
), в чем разница между два?
Разница между == и ===
Ответ 1
Короче:
==
оператор проверяет, равны ли значения их экземпляров "equal to"
===
оператор проверяет, указывают ли ссылки на один и тот же экземпляр, "identical to"
Длинный ответ:
Классы являются ссылочными типами, несколько констант и переменных могут ссылаться на один и тот же экземпляр класса за кулисами. Ссылки на классы остаются в стеке времени выполнения (RTS), а их экземпляры остаются в области кучи памяти. Когда вы контролируете равенство с помощью ==
это означает, что их экземпляры равны друг другу. Это не должен быть один и тот же экземпляр, чтобы быть равным. Для этого вам нужно предоставить критерии равенства для вашего пользовательского класса. По умолчанию пользовательские классы и структуры не получают реализацию операторов эквивалентности по умолчанию, известную как операторы "равный" ==
и оператор "не равный" !=
. Чтобы сделать это, ваш пользовательский класс должен соответствовать протоколу Equatable
и его static func == (lhs:, rhs:) → Bool
Давайте посмотрим на пример:
class Person : Equatable {
let ssn: Int
let name: String
init(ssn: Int, name: String) {
self.ssn = ssn
self.name = name
}
static func == (lhs: Person, rhs: Person) -> Bool {
return lhs.ssn == rhs.ssn
}
}
PS:
как ssn (номер социального страхования) является уникальным номером, вам не нужно сравнивать, если их имена равны или нет.
let person1 = Person(ssn: 5, name: "Bob")
let person2 = Person(ssn: 5, name: "Bob")
if person1 == person2 {
print("the two instances are equal!")
}
Хотя ссылки на person1 и person2 указывают на два разных экземпляра в области кучи, их экземпляры равны, потому что их номера ssn равны. Так что на выходе будут the two instance are equal!
if person1 === person2 {
//It does not enter here
} else {
print("the two instances are not identical!")
}
===
Оператор проверяет, указывают ли ссылки на один и тот же экземпляр, "identical to"
. Поскольку person1 и person2 имеют два разных экземпляра в области кучи, они не идентичны, а выходные данные the two instance are not identical!
let person3 = person1
PS:
классы являются ссылочными типами, и ссылка person1 копируется в person3 с помощью этой операции присваивания, таким образом, обе ссылки указывают на один и тот же экземпляр в области кучи.
if person3 === person1 {
print("the two instances are identical!")
}
Они идентичны, и на выходе будут the two instances are identical!
Ответ 2
!==
и ===
являются операторами идентичности и используются для определения того, имеют ли два объекта одну и ту же ссылку.
Swift также предоставляет два идентификационных оператора (=== и! ==), которые вы используете для проверки того, ссылаются ли две ссылки на объекты на один и тот же экземпляр объекта.
Отрывок из: Apple Inc. "Быстрый язык программирования". интерактивные книги. https://itun.es/us/jEUH0.l
Ответ 3
В Objective-C и Swift операторы ==
и !=
NSUInteger
равенство значений для NSUInteger
значений (например, NSInteger
, NSUInteger
, int
, в Objective-C и Int
, UInt
и т.д. В Swift). Для объектов (NSObject/NSNumber и подклассов в Objective-C и ссылочных типов в Swift) ==
и !=
Проверяют, что объекты/ссылочные типы - это одно и то же, т.е. Одно и то же хеш-значение, или не совпадают одинаковая вещь соответственно.
let a = NSObject()
let b = NSObject()
let c = a
a == b // false
a == c // true
Быстрые операторы равенства тождеств, ===
и !==
, проверяют ссылочное равенство - и, таким образом, вероятно, должны называться операторами ссылочного равенства IMO.
a === b // false
a === c // true
Стоит также отметить, что пользовательские ссылочные типы в Swift (которые не подклассируют класс, соответствующий Equatable) не реализуют автоматически операторы равенства, но операторы равенства идентичности по-прежнему применяются. Также, путем реализации ==
!=
Автоматически реализуется.
class MyClass: Equatable {
let myProperty: String
init(s: String) {
myProperty = s
}
}
func ==(lhs: MyClass, rhs: MyClass) -> Bool {
return lhs.myProperty == rhs.myProperty
}
let myClass1 = MyClass(s: "Hello")
let myClass2 = MyClass(s: "Hello")
myClass1 == myClass2 // true
myClass1 != myClass2 // false
myClass1 === myClass2 // false
myClass1 !== myClass2 // true
Эти операторы равенства не реализованы для других типов, таких как структуры на любом языке. Однако пользовательские операторы могут быть созданы в Swift, что, например, позволит вам создать оператор для проверки равенства CGPoint.
infix operator <==> { precedence 130 }
func <==> (lhs: CGPoint, rhs: CGPoint) -> Bool {
return lhs.x == rhs.x && lhs.y == rhs.y
}
let point1 = CGPoint(x: 1.0, y: 1.0)
let point2 = CGPoint(x: 1.0, y: 1.0)
point1 <==> point2 // true
Ответ 4
Свифт 3 и выше
===
(или !==
)
- Проверяет, идентичны ли значения (оба указывают на один и тот же адрес памяти).
- Сравнение ссылочных типов.
- Как
==
в Obj-C (равенство указателей).
==
(или !=
)
- Проверки, если значения совпадают.
- Сравнение типов значений.
- Как и по умолчанию
isEqual:
в поведении Obj-C.
Здесь я сравниваю три экземпляра (класс является ссылочным типом)
class Person {}
let person = Person()
let person2 = person
let person3 = Person()
person === person2 // true
person === person3 // false
Ответ 5
Существуют тонкости с Swifts ===
, которые выходят за рамки простой арифметики указателя. Хотя в Objective-C вы смогли сравнить любые два указателя (т.е. NSObject *
) с ==
, это больше не верно в Swift, так как типы во время компиляции играют гораздо большую роль.
Игровая площадка даст вам
1 === 2 // false
1 === 1 // true
let one = 1 // 1
1 === one // compile error: Type 'Int' does not conform to protocol 'AnyObject'
1 === (one as AnyObject) // true (surprisingly (to me at least))
С помощью строк нам придется привыкнуть к этому:
var st = "123" // "123"
var ns = (st as NSString) // "123"
st == ns // true, content equality
st === ns // compile error
ns === (st as NSString) // false, new struct
ns === (st as AnyObject) // false, new struct
(st as NSString) === (st as NSString) // false, new structs, bridging is not "free" (as in "lunch")
NSString(string:st) === NSString(string:st) // false, new structs
var st1 = NSString(string:st) // "123"
var st2 = st1 // "123"
st1 === st2 // true
var st3 = (st as NSString) // "123"
st1 === st3 // false
(st as AnyObject) === (st as AnyObject) // false
но тогда вы также можете получить удовольствие:
var st4 = st // "123"
st4 == st // true
st4 += "5" // "1235"
st4 == st // false, not quite a reference, copy on write semantics
Я уверен, что вы можете придумать гораздо более забавные случаи: -)
Обновление для Swift 3 (как было предложено в комментарии от Jakub Truhlář)
1===2 // Compiler error: binary operator '===' cannot be applied to two 'Int' operands
(1 as AnyObject) === (2 as AnyObject) // false
let two = 2
(2 as AnyObject) === (two as AnyObject) // false (rather unpleasant)
(2 as AnyObject) === (2 as AnyObject) // false (this makes it clear that there are new objects being generated)
Это выглядит немного более согласованным с Type 'Int' does not conform to protocol 'AnyObject'
, однако мы получаем
type(of:(1 as AnyObject)) // _SwiftTypePreservingNSNumber.Type
но явное преобразование дает понять, что может быть что-то происходит.
На String-стороне вещей NSString
все равно будет доступно до тех пор, пока мы import Cocoa
. Тогда мы будем иметь
var st = "123" // "123"
var ns = (st as NSString) // "123"
st == ns // Compile error with Fixit: 'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?
st == ns as String // true, content equality
st === ns // compile error: binary operator '===' cannot be applied to operands of type 'String' and 'NSString'
ns === (st as NSString) // false, new struct
ns === (st as AnyObject) // false, new struct
(st as NSString) === (st as NSString) // false, new structs, bridging is not "free" (as in "lunch")
NSString(string:st) === NSString(string:st) // false, new objects
var st1 = NSString(string:st) // "123"
var st2 = st1 // "123"
st1 === st2 // true
var st3 = (st as NSString) // "123"
st1 === st3 // false
(st as AnyObject) === (st as AnyObject) // false
До сих пор сбивает с толку два класса String, но отказ от неявного преобразования, вероятно, сделает его более ощутимым.
Ответ 6
Например, если вы создаете два экземпляра класса, например. myClass
:
var inst1 = myClass()
var inst2 = myClass()
вы можете сравнить эти экземпляры,
if inst1 === inst2
цитируется:
который вы используете для проверки того, ссылаются ли две ссылки на объекты на тот же экземпляр объекта.
Отрывок из: Apple Inc. "Быстрый язык программирования". интерактивные книги. https://itun.es/sk/jEUH0.l
Ответ 7
В Swift у нас есть === simbol, что означает, что оба объекта ссылаются на один и тот же адресный адрес
class SomeClass {
var a: Int;
init(_ a: Int) {
self.a = a
}
}
var someClass1 = SomeClass(4)
var someClass2 = SomeClass(4)
someClass1 === someClass2 // false
someClass2 = someClass1
someClass1 === someClass2 // true
Ответ 8
Небольшой вклад, связанный с объектом Any
.
Я работал с модульными тестами вокруг NotificationCenter
, который использует Any
как параметр, который я хотел сравнить для равенства.
Однако, поскольку Any
не может использоваться в операции равенства, необходимо было его изменить. В конечном счете, я остановился на следующем подходе, который позволил мне получить равенство в моей конкретной ситуации, показанной здесь с упрощенным примером:
func compareTwoAny(a: Any, b: Any) -> Bool {
return ObjectIdentifier(a as AnyObject) == ObjectIdentifier(b as AnyObject)
}
Эта функция использует ObjectIdentifier, которая предоставляет уникальный адрес для объекта, что позволяет мне протестировать.
Один элемент, который нужно отметить примерно ObjectIdentifier
за Apple по приведенной выше ссылке:
В Swift только экземпляры экземпляров и метатипы имеют уникальные идентификаторы. Нет понятия идентичности для структур, перечислений, функций или кортежи.
Ответ 9
==
используется для проверки, равны ли две переменные, т.е. 2 == 2
. Но в случае ===
это означает равенство, т.е. если два экземпляра ссылаются на один и тот же объектный пример в случае классов, создается ссылка, которая сохраняется во многих других экземплярах.
Ответ 10
Swift 4: еще один пример использования модульных тестов, который работает только с ===
Примечание: Тест ниже не проходит с ==, работает с ===
func test_inputTextFields_Delegate_is_ViewControllerUnderTest() {
//instantiate viewControllerUnderTest from Main storyboard
let storyboard = UIStoryboard(name: "Main", bundle: nil)
viewControllerUnderTest = storyboard.instantiateViewController(withIdentifier: "StoryBoardIdentifier") as! ViewControllerUnderTest
let _ = viewControllerUnderTest.view
XCTAssertTrue(viewControllerUnderTest.inputTextField.delegate === viewControllerUnderTest)
}
И класс существо
class ViewControllerUnderTest: UIViewController, UITextFieldDelegate {
@IBOutlet weak var inputTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
inputTextField.delegate = self
}
}
Ошибка в модульных тестах, если вы используете == is, Binary operator '==' cannot be applied to operands of type 'UITextFieldDelegate?' and 'ViewControllerUnderTest!'
Binary operator '==' cannot be applied to operands of type 'UITextFieldDelegate?' and 'ViewControllerUnderTest!'
Ответ 11
-
Ценность равенства
- Цель-C:
isEqual:
- Свифт:
==
- Цель-C:
-
Справочное равенство
- Objective-C:
==
- Свифт:
===
- Objective-C:
Узнайте больше здесь
Ответ 12
(==) будет проверять, имеют ли оба значения одинаковые или нет, если (а == Ь) {//значение}
но (===) проверит значение, а также тип эти переменные, если это то же самое или нет..!! if (a === b) {//значение и тип данных}
спасибо,