10 ответов:
короче:
==оператор проверяет, равны ли их значения экземпляра,"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 } }
P.S.:поскольку 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
P.S:классы являются ссылочными типами и person1 ссылка копируется в person3 с этой операцией присваивания, таким образом, обе ссылки указывают на один и тот же экземпляр в области кучи.if person3 === person1 { print("the two instances are identical!") }они идентичны и выход будет
the two instances are identical!
!==и===являются операторами идентификации и используются для определения того, имеют ли два объекта одну и ту же ссылку.Swift также предоставляет два оператора идентификации (=== и != = ), который используется для проверки того, ссылаются ли две ссылки на объект на один и тот же экземпляр объекта.
Отрывок Из: Apple Inc. "Язык Программирования Swift."iBooks. https://itun.es/us/jEUH0.l
как в Objective-C, так и в Swift, the
==и!=операторы проверяют равенство значений для числовых значений (например,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Свифт тож равенства операторы
===и!==, проверьте ссылочное равенство, и, таким образом, вероятно, следует называть равенство ссылок операторы ИМО.a === b // false a === c // trueтакже стоит отметить, что пользовательские ссылочные типы в Swift (которые не подклассируют класс, соответствующий Equatable) автоматически не реализуют операторы equal to, но тож равенства операторы все еще применяются. Кроме того, путем реализации
==,!=автоматически реализован.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
есть тонкости со Стриж
===это выходит за рамки простой арифметики указателя. В то время как в Objective-C вы смогли сравнить любые два указателя (т. е.NSObject *) С==это уже не так быстро так как типы играют гораздо большую роль во время компиляции.детская площадка даст вам
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 (как предлагается в комментарии от Якуб 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но явное преобразование дает понять, что там может быть что-то происходит. На струнной стороне вещей
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по-прежнему запутанно иметь два строковых класса, но удаление неявного преобразования, вероятно, сделает его мало более ощутима.
в swift 3 и выше
===(или!==)
- проверяет, если значения одинаковых(оба указывают на один и тот же адрес памяти).
- сравнение ссылка типа.
- как
==В Obj-C (равенство указателей).
==(или!=)
- проверяет, если значения тот же.
- сравнение типы значений.
- как по умолчанию
isEqual:в Obj-C и поведения.здесь я сравниваю три экземпляра(класс является ссылочным типом)
class Person {} let person = Person() let person2 = person let person3 = Person() person === person2 // true person === person3 // false
например, если вы создаете два экземпляра класса, например
myClass:var inst1 = myClass() var inst2 = myClass()вы можете сравнить эти экземпляры,
if inst1 === inst2цитирую:
который вы используете для проверки того, относятся ли две ссылки на объекты к тот же экземпляр объекта.
Отрывок Из: Apple Inc. "Язык Программирования Swift."iBooks. https://itun.es/sk/jEUH0.l
в 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
просто незначительный вклад, связанный с С
Anyне может использоваться в операции равенства, необходимо было изменить его. В конечном счете, я остановился на следующем подходе, который позволил мне получить равенство в моей конкретной ситуации, показанной здесь с упрощенным пример:func compareTwoAny(a: Any, b: Any) -> Bool { return ObjectIdentifier(a as AnyObject) == ObjectIdentifier(b as AnyObject) }эта функция использует ObjectIdentifier, который предоставляет уникальный адрес для объекта, что позволяет мне проверить.
один пункт, чтобы отметить, хотя о
ObjectIdentifierза Яблоко по ссылке выше:в Swift только экземпляры классов и метатипы имеют уникальные идентификаторы. Нет понятия идентичности для структур, перечислений, функций или кортежи.
==используется для проверки равенства двух переменных, т. е.2 == 2. Но в случае===это означает равенство, т. е. если два экземпляра ссылаются на один и тот же пример объекта в случае классов создается ссылка, которая хранится во многих других экземплярах.
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!'
Comments