Dans swift, il semble y avoir deux opérateurs d'égalité: le double égal ( ==
) et le triple égal ( ===
), quelle est la différence entre les deux?
En bref:
==
l'opérateur vérifie si leurs valeurs d'instance sont égales, "equal to"
===
l'opérateur vérifie si les références pointent vers la même instance, "identical to"
Longue réponse:
Les classes sont des types de référence, il est possible que plusieurs constantes et variables se réfèrent à la même instance unique d'une classe dans les coulisses. Les références de classe restent dans Run Time Stack (RTS) et leurs instances restent dans la zone Heap de la mémoire. Lorsque vous contrôlez l'égalité avec, ==
cela signifie que leurs instances sont égales les unes aux autres. Il n'est pas nécessaire que la même instance soit identique. Pour cela, vous devez fournir des critères d'égalité à votre classe personnalisée. Par défaut, les classes et structures personnalisées ne reçoivent pas d'implémentation par défaut des opérateurs d'équivalence, appelés opérateurs «égal à» ==
et «non égal à» !=
. Pour ce faire, votre classe personnalisée doit respecter le Equatable
protocole et sa static func == (lhs:, rhs:) -> Bool
fonction
Regardons l'exemple:
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.:
Étant donné que ssn (numéro de sécurité sociale) est un numéro unique, vous n'avez pas besoin de comparer si leur nom est égal ou non.
let person1 = Person(ssn: 5, name: "Bob")
let person2 = Person(ssn: 5, name: "Bob")
if person1 == person2 {
print("the two instances are equal!")
}
Bien que les références person1 et person2 pointent deux instances différentes dans la zone Heap, leurs instances sont égales car leurs numéros SSN sont égaux. Ainsi, la sortie serathe two instance are equal!
if person1 === person2 {
//It does not enter here
} else {
print("the two instances are not identical!")
}
===
opérateur vérifie si les références pointent la même instance, "identical to"
. Étant donné que personne1 et personne2 ont deux instances différentes dans la zone Heap, elles ne sont pas identiques et la sortiethe two instance are not identical!
let person3 = person1
P.S:
Les classes sont des types de référence et la référence de person1 est copiée dans person3 avec cette opération d'affectation, les deux références pointent donc la même instance dans la zone Heap.
if person3 === person1 {
print("the two instances are identical!")
}
Ils sont identiques et la sortie sera the two instances are identical!
!==
et ===
sont des opérateurs d'identité et sont utilisés pour déterminer si deux objets ont la même référence.
Swift fournit également deux opérateurs d'identité (=== et! ==), que vous utilisez pour tester si deux références d'objet font toutes deux référence à la même instance d'objet.
Extrait de: Apple Inc. «The Swift Programming Language». iBooks. https://itun.es/us/jEUH0.l
==
isisEqual:
, ou l'équivalence sémantique définie par la classe.===
dans Swift est==
dans (Obj) C - égalité de pointeur, ou identité d'objet.var
oulet
) d'un nom à une valeur est une copie unique - il est donc inutile de créer des pointeurs car la valeur à laquelle vous avez fait un pointeur est une valeur différente de celle que vous avez créée en premier. Un autre est que la définition de la sémantique des valeurs par Swift supprime le stockage - le compilateur est libre d'optimiser, jusqu'à et y compris ne jamais stocker votre valeur à un emplacement de mémoire accessible au-delà de la ligne où elle est utilisée (registre, encodage d'instructions, etc.).Dans les deux Objective-C et Swift, les
==
et!=
opérateurs test pour l' égalité de valeur pour les valeurs numériques (par exempleNSInteger
,NSUInteger
,int
, en Objective-C etInt
,UInt
, etc. Swift). Pour les objets (NSObject / NSNumber et les sous-classes dans Objective-C et les types de référence dans Swift),==
et!=
tester que les objets / types de référence sont la même chose identique - c'est-à-dire la même valeur de hachage - ou ne sont pas la même chose identique, respectivement .Les opérateurs d' égalité d'identité de Swift ,
===
et!==
vérifier l'égalité référentielle - et donc, devraient probablement être appelés les opérateurs d' égalité référentielle IMO.Il convient également de souligner que les types de référence personnalisés dans Swift (qui ne sous-classent pas une classe conforme à Equatable) n'implémentent pas automatiquement les opérateurs égaux à, mais les opérateurs d' égalité d'identité s'appliquent toujours. En outre, en implémentant
==
,!=
est implémenté automatiquement.Ces opérateurs d'égalité ne sont pas implémentés pour d'autres types tels que les structures dans les deux langues. Cependant, des opérateurs personnalisés peuvent être créés dans Swift, ce qui vous permettrait, par exemple, de créer un opérateur pour vérifier l'égalité d'un CGPoint.
la source
==
ne teste pas l'NSNumber
égalité dans Objective-C.NSNumber
estNSObject
donc un test d'identité. La raison pour laquelle cela fonctionne PARFOIS est à cause des pointeurs marqués / des littéraux d'objets mis en cache. Il échouera pour des nombres suffisamment grands et sur des appareils 32 bits lors de la comparaison de non-littéraux.Dans swift 3 et au-dessus
===
(ou!==
)==
dans Obj-C (égalité de pointeur).==
(ou!=
)isEqual:
par défaut dans le comportement Obj-C.Ici, je compare trois instances (la classe est un type de référence)
la source
isEqual:
dans Swift:override func isEqual(_ object: Any?) -> Bool {}
Il y a des subtilités avec les martinets
===
qui vont au-delà de la simple arithmétique des pointeurs. Dans Objective-C, vous avez pu comparer deux pointeurs (c.-à-d.NSObject *
) Avec==
cela n'est plus vrai dans Swift car les types jouent un rôle beaucoup plus important pendant la compilation.Un terrain de jeu vous donnera
Avec les chaînes, nous devrons nous habituer à ceci:
mais vous pouvez aussi vous amuser comme suit:
Je suis sûr que vous pouvez penser à des cas beaucoup plus drôles :-)
Mise à jour pour Swift 3 (comme suggéré par le commentaire de Jakub Truhlář)
Cela semble un peu plus cohérent avec
Type 'Int' does not conform to protocol 'AnyObject'
, mais nous obtenons ensuitemais la conversion explicite montre clairement qu'il pourrait y avoir quelque chose. Du côté des chaînes, les choses
NSString
seront toujours disponibles aussi longtemps que nousimport Cocoa
. Ensuite, nous auronsIl est toujours déroutant d'avoir deux classes String, mais abandonner la conversion implicite la rendra probablement un peu plus palpable.
la source
===
opérateur pour comparerInts
. Pas dans Swift 3.===
n'a pas de sens pour les structures car ce sont des types de valeur. En particulier, vous devez garder à l'esprit trois types: les types littéraux, tels que 1 ou "foo", qui ne sont pas liés à une variable et n'affectent normalement que la compilation, car vous ne les traitez généralement pas pendant l'exécution; types de struct tels queInt
etString
qui sont ce que vous obtenez lorsque vous affectez un littéral à une variable, et des classes telles queAnyObject
etNSString
.Par exemple, si vous créez deux instances d'une classe, par exemple
myClass
:vous pouvez comparer ces instances,
cité:
Extrait de: Apple Inc. «The Swift Programming Language». iBooks. https://itun.es/sk/jEUH0.l
la source
Dans Swift, nous avons === simbol, ce qui signifie que les deux objets font référence à la même référence et à la même adresse
la source
Juste une petite contribution liée à l'
Any
objet.Je travaillais avec des tests unitaires autour
NotificationCenter
, qui utiliseAny
comme paramètre que je voulais comparer pour l'égalité.Cependant,
Any
ne pouvant pas être utilisé dans une opération d'égalité, il a fallu le modifier. En fin de compte, j'ai opté pour l'approche suivante, qui m'a permis d'obtenir l'égalité dans ma situation spécifique, présentée ici avec un exemple simpliste:Cette fonction tire parti d' ObjectIdentifier , qui fournit une adresse unique pour l'objet, me permettant de tester.
Un élément à noter cependant
ObjectIdentifier
par Apple sur le lien ci-dessus:la source
==
est utilisé pour vérifier si deux variables sont égales ie2 == 2
. Mais dans le cas où===
cela signifie égalité, c'est-à-dire que si deux instances se référant au même exemple d'objet dans le cas des classes, une référence est créée qui est détenue par de nombreuses autres instances.la source
Swift 4: Un autre exemple utilisant des tests unitaires qui ne fonctionne qu'avec ===
Remarque: le test ci-dessous échoue avec ==, fonctionne avec ===
Et la classe étant
L'erreur dans les tests unitaires si vous utilisez == est,
Binary operator '==' cannot be applied to operands of type 'UITextFieldDelegate?' and 'ViewControllerUnderTest!'
la source