No Swift, parece haver dois operadores de igualdade: o dobro é igual a ( ==
) e o triplo é igual a ===
), qual é a diferença entre os dois?
Em resumo:
==
O operador verifica se seus valores de instância são iguais, "equal to"
===
O operador verifica se as referências apontam para a mesma instância, "identical to"
Resposta longa:
Classes são tipos de referência, é possível que várias constantes e variáveis se refiram à mesma instância única de uma classe nos bastidores. As referências de classe permanecem no RTS (Run Time Stack) e suas instâncias permanecem na área Heap da Memória. Quando você controla a igualdade ==
, significa se as instâncias são iguais entre si. Não precisa ser a mesma instância para ser igual. Para isso, você precisa fornecer um critério de igualdade para sua classe personalizada. Por padrão, as classes e estruturas personalizadas não recebem uma implementação padrão dos operadores de equivalência, conhecidos como operador "igual a" ==
e "não igual a" !=
. Para fazer isso, sua classe personalizada precisa estar em conformidade com o Equatable
protocolo e sua static func == (lhs:, rhs:) -> Bool
função
Vejamos o exemplo:
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.:
Como ssn (número de segurança social) é um número único, você não precisa comparar se o nome deles é igual ou não.
let person1 = Person(ssn: 5, name: "Bob")
let person2 = Person(ssn: 5, name: "Bob")
if person1 == person2 {
print("the two instances are equal!")
}
Embora as referências person1 e person2 apontem duas instâncias diferentes na área Heap, suas instâncias são iguais porque seus números ssn são iguais. Então a saída seráthe two instance are equal!
if person1 === person2 {
//It does not enter here
} else {
print("the two instances are not identical!")
}
===
O operador verifica se as referências apontam para a mesma instância "identical to"
,. Como person1 e person2 têm duas instâncias diferentes na área Heap, elas não são idênticas e a saídathe two instance are not identical!
let person3 = person1
P.S:
Classes são tipos de referência e a referência de person1 é copiada para person3 com esta operação de atribuição, portanto, ambas as referências apontam a mesma instância na área Heap.
if person3 === person1 {
print("the two instances are identical!")
}
Eles são idênticos e a saída será the two instances are identical!
!==
e ===
são operadores de identidade e são usados para determinar se dois objetos têm a mesma referência.
O Swift também fornece dois operadores de identidade (=== e! ==), que você usa para testar se duas referências a objetos se referem à mesma instância de objeto.
Trecho de: Apple Inc. “A linguagem de programação Swift”. iBooks. https://itun.es/us/jEUH0.l
==
éisEqual:
ou equivalência semântica definida por classe.===
em Swift está==
em (Obj) C - igualdade de ponteiro ou identidade de objeto.var
oulet
) de um nome a um valor é uma cópia exclusiva - portanto, não faz sentido criar ponteiros porque o valor para o qual você fez um ponteiro é um valor diferente daquele que você criou primeiro. Outra é que a definição de semântica de valores de Swift abstrai o armazenamento - o compilador é livre para otimizar, inclusive incluindo nunca armazenar seu valor em um local de memória acessível além da linha em que é usado (registro, codificação de instruções etc.).Em ambos Objectivo-C e Swift, a
==
e!=
teste de operadores para a igualdade valor para valores de número (por exemplo,NSInteger
,NSUInteger
,int
, em Objective-C eInt
,UInt
, etc., em Swift). Para objectos (NSObject / NSNumber e subclasses em Objective-C e tipos de referência em Swift),==
e!=
teste que os objetos / tipos de referência são a mesma coisa idêntica - ou seja, o mesmo valor de hash - ou não são a mesma coisa idêntica, respectivamente .Os operadores de igualdade de identidade de Swift
===
e!==
, verificam a igualdade referencial - e, portanto, provavelmente devem ser chamados de operadores de igualdade referencial IMO.Também vale ressaltar que os tipos de referência personalizados no Swift (que não subclassificam uma classe que é compatível com Equatable) não implementam automaticamente o igual a operadores, mas os operadores de igualdade de identidade ainda se aplicam. Além disso, implementando
==
,!=
é implementado automaticamente.Esses operadores de igualdade não são implementados para outros tipos, como estruturas em qualquer idioma. No entanto, operadores personalizados podem ser criados no Swift, o que, por exemplo, permitiria criar um operador para verificar a igualdade de um CGPoint.
fonte
==
não testa aNSNumber
igualdade no Objective-C.NSNumber
é umNSObject
teste para identidade. A razão pela qual SOMETIMES funciona é por causa de literais de ponteiros / objetos em cache marcados. Ele falhará em números grandes o suficiente e em dispositivos de 32 bits ao comparar não literais.No rápido 3 e acima
===
(ou!==
)==
no Obj-C (igualdade de ponteiro).==
(ou!=
)isEqual:
no comportamento Obj-C.Aqui eu comparo três instâncias (classe é um tipo de referência)
fonte
isEqual:
no Swift:override func isEqual(_ object: Any?) -> Bool {}
Existem sutilezas com Swifts
===
que vão além da mera aritmética de ponteiros. Enquanto em Objective-C, você foi capaz de comparar dois ponteiros (ieNSObject *
) com==
isso não é mais verdade no Swift, pois os tipos desempenham um papel muito maior durante a compilação.Um Playground lhe dará
Com as strings, teremos que nos acostumar com isso:
mas você também pode se divertir da seguinte maneira:
Tenho certeza que você pode pensar em casos muito mais engraçados :-)
Atualização para o Swift 3 (conforme sugerido pelo comentário de Jakub Truhlář)
Isso parece um pouco mais consistente com
Type 'Int' does not conform to protocol 'AnyObject'
, no entanto, obtemosmas a conversão explícita deixa claro que pode haver algo acontecendo. No lado das strings, as coisas
NSString
ainda estarão disponíveis enquanto nósimport Cocoa
. Então teremosAinda é confuso ter duas classes String, mas descartar a conversão implícita provavelmente a tornará um pouco mais palpável.
fonte
===
operador para compararInts
. Not in Swift 3.===
não faz sentido para estruturas, pois são tipos de valor. Em particular, há três tipos que você deve ter em mente: tipos literais, como 1 ou "foo", que não foram vinculados a uma variável e normalmente afetam apenas a compilação, pois geralmente você não lida com eles durante o tempo de execução; struct tipos comoInt
eString
quais são o que você obtém quando atribui um literal a uma variável e classes comoAnyObject
eNSString
.Por exemplo, se você criar duas instâncias de uma classe, por exemplo
myClass
:você pode comparar essas instâncias,
citado:
Trecho de: Apple Inc. “A linguagem de programação Swift”. iBooks. https://itun.es/sk/jEUH0.l
fonte
Em Swift, temos === simbol, o que significa que ambos os objetos estão se referindo à mesma referência e mesmo endereço
fonte
Apenas uma pequena contribuição relacionada ao
Any
objeto.Eu estava trabalhando com testes de unidade
NotificationCenter
, que faz uso deAny
como parâmetro que eu queria comparar para igualdade.No entanto, como
Any
não pode ser usado em uma operação de igualdade, foi necessário alterá-lo. Por fim, decidi pela seguinte abordagem, que me permitiu obter igualdade em minha situação específica, mostrada aqui com um exemplo simplista:Esta função tira proveito do ObjectIdentifier , que fornece um endereço exclusivo para o objeto, permitindo que eu teste.
Um item a ser observado
ObjectIdentifier
por Apple no link acima:fonte
==
é usado para verificar se duas variáveis são iguais, ie2 == 2
. Porém, no caso de===
representar igualdade, isto é, se duas instâncias referentes ao mesmo objeto exemplo, no caso de classes, for criada uma referência que é mantida por muitas outras instâncias.fonte
Swift 4: Outro exemplo usando testes de unidade que funciona apenas com ===
Nota: O teste abaixo falha com ==, funciona com ===
E a classe sendo
O erro nos testes de unidade se você usar == é,
Binary operator '==' cannot be applied to operands of type 'UITextFieldDelegate?' and 'ViewControllerUnderTest!'
fonte