transportation the significado programming programación lenguaje language español descargar swift

swift - the - Diferencia entre== y===



swift(lenguaje de programación) (10)

En Swift parece haber dos operadores de igualdad: el doble es igual a ( == ) y el triple es igual a ( === ), ¿cuál es la diferencia entre los dos?


En Swift 3 y arriba

=== (o !== )

  • Comprueba si los valores son idénticos (ambos apuntan a la misma dirección de memoria) .
  • Comparando tipos de referencia .
  • Como == en Obj-C (igualdad de puntero).

== (o != )

  • Comprueba si los valores son los mismos .
  • Comparando tipos de valores .
  • Al igual que el predeterminado isEqual: en el comportamiento de Obj-C.

Aquí comparo tres instancias (la clase es un tipo de referencia)

class Person {} let person = Person() let person2 = person let person3 = Person() person === person2 // true person === person3 // false


En Swift tenemos === símbolo, lo que significa que ambos objetos se refieren a la misma dirección de referencia

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


Hay sutilezas con Swifts === que van más allá de la mera aritmética de punteros. Mientras que en Objective-C pudo comparar dos punteros (es decir, NSObject * ) con == esto ya no es cierto en Swift, ya que los tipos juegan un papel mucho mayor durante la compilación.

Un patio de recreo te dará

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))

Con cuerdas tendremos que acostumbrarnos a esto:

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

Pero también puedes divertirte de la siguiente manera:

var st4 = st // "123" st4 == st // true st4 += "5" // "1235" st4 == st // false, not quite a reference, copy on write semantics

Estoy seguro de que puedes pensar en muchos casos más divertidos :-)

Actualización para Swift 3 (como lo sugiere el comentario de 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)

Esto parece un poco más coherente con el Type ''Int'' does not conform to protocol ''AnyObject'' , pero luego obtenemos

type(of:(1 as AnyObject)) // _SwiftTypePreservingNSNumber.Type

pero la conversión explícita deja claro que puede haber algo en marcha. En el lado de la cadena de cosas, NSString seguirá estando disponible siempre que NSString import Cocoa . Entonces tendremos

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

Todavía es confuso tener dos clases de String, pero si se elimina la conversión implícita, probablemente sea más palpable.


Por ejemplo, si creas dos instancias de una clase, por ejemplo, myClass :

var inst1 = myClass() var inst2 = myClass()

puedes comparar esos casos,

if inst1 === inst2

citado

que utiliza para probar si dos referencias de objeto se refieren a la misma instancia de objeto.

Extracto de: Apple Inc. "El lenguaje de programación Swift". IBooks. https://itun.es/sk/jEUH0.l


Solo una pequeña contribución relacionada con el objeto Any .

Trabajaba con pruebas unitarias en torno a NotificationCenter , que utiliza Any como un parámetro que quería comparar para la igualdad.

Sin embargo, dado que Any no se puede utilizar en una operación de igualdad, fue necesario cambiarlo. En última instancia, me decidí por el siguiente enfoque, que me permitió obtener igualdad en mi situación específica, que se muestra aquí con un ejemplo simplista:

func compareTwoAny(a: Any, b: Any) -> Bool { return ObjectIdentifier(a as AnyObject) == ObjectIdentifier(b as AnyObject) }

Esta función aprovecha ObjectIdentifier , que proporciona una dirección única para el objeto, lo que me permite probar.

Un elemento a tener en cuenta sobre ObjectIdentifier por Apple en el enlace anterior:

En Swift, solo las instancias de clase y los metatipos tienen identidades únicas. No hay noción de identidad para estructuras, enumeraciones, funciones o tuplas.


Tanto en Objective-C como en Swift, los operadores == y != NSUInteger igualdad de valores para valores numéricos (por ejemplo, NSInteger , NSUInteger , int , en Objective-C e Int , UInt , etc. en Swift). Para objetos (NSObject / NSNumber y subclases en Objective-C y tipos de referencia en Swift), == y != Comprueban que los objetos / tipos de referencia son lo mismo - es decir, el mismo valor hash - o no son lo mismo Lo idéntico, respectivamente.

let a = NSObject() let b = NSObject() let c = a a == b // false a == c // true

Los operadores de igualdad de identidad de Swift, === y !== , verifican la igualdad referencial, y por lo tanto, probablemente deberían llamarse los operadores de igualdad referencial de la OMI.

a === b // false a === c // true

También vale la pena señalar que los tipos de referencia personalizados en Swift (que no subclasifican una clase que se ajusta a Equatable) no implementan automáticamente el igual a los operadores, pero los operadores de igualdad de identidad aún se aplican. Además, al implementar == != Se implementa automáticamente.

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

Estos operadores de igualdad no se implementan para otros tipos, como estructuras en cualquier idioma. Sin embargo, los operadores personalizados se pueden crear en Swift, lo que, por ejemplo, le permitiría crear un operador para verificar la igualdad de un 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


!== y === son operadores de identidad y se utilizan para determinar si dos objetos tienen la misma referencia.

Swift también proporciona dos operadores de identidad (=== y! ==), que utiliza para probar si dos referencias de objeto se refieren a la misma instancia de objeto.

Extracto de: Apple Inc. "El lenguaje de programación Swift". IBooks. https://itun.es/us/jEUH0.l


== se utiliza para verificar si dos variables son iguales, es decir, 2 == 2 . Pero en el caso de === significa igualdad, es decir, si se crean dos instancias que se refieren al mismo ejemplo de objeto en el caso de las clases, se crea una referencia que es mantenida por muchas otras instancias.


En breve:

== operador comprueba si sus valores de instancia son iguales, "equal to"

=== operador === comprueba si las referencias apuntan a la misma instancia, "identical to"

Respuesta larga:

Las clases son tipos de referencia, es posible que varias constantes y variables se refieran a la misma instancia única de una clase detrás de escena. Las referencias de clase permanecen en la pila de tiempo de ejecución (RTS) y sus instancias permanecen en el área de almacenamiento dinámico de la memoria. Cuando controlas la igualdad con == significa que sus instancias son iguales entre sí. No necesita ser la misma instancia para ser igual. Para ello, debe proporcionar un criterio de igualdad a su clase personalizada. De forma predeterminada, las clases y estructuras personalizadas no reciben una implementación predeterminada de los operadores de equivalencia, conocidos como el operador "igual a" == y el operador "no es igual a" != . Para hacer esto, su clase personalizada debe cumplir Equatable protocolo Equatable y su static func == (lhs:, rhs:) -> Bool Función static func == (lhs:, rhs:) -> Bool

Veamos el ejemplo:

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: Dado que ssn (número de seguro social) es un número único, no necesita comparar si su nombre es igual o no.

let person1 = Person(ssn: 5, name: "Bob") let person2 = Person(ssn: 5, name: "Bob") if person1 == person2 { print("the two instances are equal!") }

Aunque las referencias de persona1 y persona2 señalan dos instancias diferentes en el área del montón, sus instancias son iguales porque sus números ssn son iguales. ¡Así que la salida serán the two instance are equal!

if person1 === person2 { //It does not enter here } else { print("the two instances are not identical!") }

=== operador === comprueba si las referencias apuntan a la misma instancia, "identical to" . Como person1 y person2 tienen dos instancias diferentes en el área de Heap, no son idénticas y la salida de the two instance are not identical!

let person3 = person1

PS: Las clases son tipos de referencia y la referencia de person1 se copia a person3 con esta operación de asignación, por lo que ambas referencias apuntan a la misma instancia en el área Heap.

if person3 === person1 { print("the two instances are identical!") }

¡Son idénticos y la salida serán the two instances are identical!


Swift 4: otro ejemplo que usa Pruebas Unitarias que solo funciona con ===

Nota: la prueba a continuación falla con ==, funciona con ===

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) }

Y la clase siendo

class ViewControllerUnderTest: UIViewController, UITextFieldDelegate { @IBOutlet weak var inputTextField: UITextField! override func viewDidLoad() { super.viewDidLoad() inputTextField.delegate = self } }

El error en Pruebas unitarias si usa == es, el Binary operator ''=='' cannot be applied to operands of type ''UITextFieldDelegate?'' and ''ViewControllerUnderTest!'' Binary operator ''=='' cannot be applied to operands of type ''UITextFieldDelegate?'' and ''ViewControllerUnderTest!''