Di swift tampaknya ada dua operator kesetaraan: ganda sama dengan ( ==
) dan tiga sama dengan ( ===
), apa perbedaan antara keduanya?
Pendeknya:
==
Operator memeriksa apakah nilai instance mereka sama, "equal to"
===
Operator memeriksa apakah referensi menunjukkan instance yang sama, "identical to"
Jawaban panjang:
Kelas adalah tipe referensi, dimungkinkan untuk konstanta berganda dan variabel untuk merujuk ke instance tunggal yang sama dari kelas di belakang layar. Referensi kelas tetap di Run Time Stack (RTS) dan instansnya tetap di area tumpukan Memori. Ketika Anda mengontrol kesetaraan dengan ==
itu berarti jika instance mereka sama satu sama lain. Tidak harus sama untuk menjadi sama. Untuk ini, Anda perlu memberikan kriteria kesetaraan untuk kelas khusus Anda. Secara default, kelas dan struktur khusus tidak menerima implementasi default dari operator ekivalen, yang dikenal sebagai operator "sama dengan" ==
dan operator "tidak sama dengan" !=
. Untuk melakukan ini, kelas khusus Anda harus menyesuaikan Equatable
protokol dan static func == (lhs:, rhs:) -> Bool
fungsinya
Mari kita lihat contohnya:
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.:
Karena ssn (nomor jaminan sosial) adalah nomor unik, Anda tidak perlu membandingkan apakah namanya sama atau tidak.
let person1 = Person(ssn: 5, name: "Bob")
let person2 = Person(ssn: 5, name: "Bob")
if person1 == person2 {
print("the two instances are equal!")
}
Walaupun referensi person1 dan person2 menunjukkan dua instance berbeda di area Heap, instance mereka sama karena angka ssnnya sama. Jadi hasilnya akanthe two instance are equal!
if person1 === person2 {
//It does not enter here
} else {
print("the two instances are not identical!")
}
===
Operator memeriksa apakah referensi menunjuk ke instance yang sama "identical to"
,. Karena person1 dan person2 memiliki dua contoh berbeda di area Heap, mereka tidak identik dan hasilnyathe two instance are not identical!
let person3 = person1
P.S:
Kelas adalah tipe referensi dan referensi person1 disalin ke person3 dengan operasi penugasan ini, sehingga kedua referensi menunjuk contoh yang sama di area Heap.
if person3 === person1 {
print("the two instances are identical!")
}
Mereka identik dan hasilnya akan seperti itu the two instances are identical!
!==
dan ===
merupakan operator identitas dan digunakan untuk menentukan apakah dua objek memiliki referensi yang sama.
Swift juga menyediakan dua operator identitas (=== dan! ==), yang Anda gunakan untuk menguji apakah dua referensi objek keduanya merujuk ke instance objek yang sama.
Kutipan dari: Apple Inc. “Bahasa Pemrograman Swift.” iBooks.https://itun.es/us/jEUH0.l
==
adalahisEqual:
, atau kesetaraan semantik yang ditentukan kelas.===
dalam Swift adalah==
dalam (Obj) C - pointer kesetaraan, atau identitas objek.var
ataulet
) nama ke nilai adalah salinan unik - jadi tidak ada artinya untuk membuat pointer karena nilai yang Anda buat pointer adalah nilai yang berbeda dari yang Anda buat pertama kali. Lain adalah bahwa definisi Swift tentang semantik nilai mengabstraksi penyimpanan - kompiler bebas untuk mengoptimalkan, hingga dan termasuk tidak pernah menyimpan nilai Anda di lokasi memori yang dapat diakses di luar garis tempat itu digunakan (register, instruksi encoding, dll).Dalam kedua Objective-C dan Swift, yang
==
dan!=
uji operator untuk nilai kesetaraan bagi nilai-nilai nomor (misalnya,NSInteger
,NSUInteger
,int
, di Objective-C danInt
,UInt
, dll di Swift). Untuk objek (NSObject / NSNumber dan subclass di Objective-C dan tipe referensi di Swift),==
dan!=
uji bahwa objek / tipe referensi adalah hal yang sama identik - yaitu, nilai hash yang sama - atau bukan hal yang sama identik, masing-masing .Operator kesetaraan identitas Swift ,
===
dan!==
, periksa kesetaraan referensial - dan karenanya, mungkin harus disebut operator kesetaraan referensial IMO.Penting juga untuk menunjukkan bahwa tipe referensi khusus di Swift (yang tidak mensubklasifikasikan kelas yang sesuai dengan Equatable) tidak secara otomatis mengimplementasikan yang sama dengan operator, tetapi identitas operator kesetaraan masih berlaku. Juga, dengan mengimplementasikan
==
,!=
secara otomatis diterapkan.Operator kesetaraan ini tidak diterapkan untuk tipe lain seperti struktur dalam bahasa apa pun. Namun, operator khusus dapat dibuat di Swift, yang akan, misalnya, memungkinkan Anda membuat operator untuk memeriksa kesetaraan CGPoint.
sumber
==
tidak mengujiNSNumber
kesetaraan dalam Objective-C.NSNumber
adalahNSObject
jadi itu menguji identitas. Alasan mengapa SOMETIMES berfungsi adalah karena penunjuk yang ditandai / objek literal yang di-cache. Ini akan gagal untuk jumlah yang cukup besar dan pada perangkat 32-bit saat membandingkan non-literal.Dalam 3 cepat dan di atas
===
(atau!==
)==
di Obj-C (pointer equality).==
(atau!=
)isEqual:
dalam perilaku Obj-C.Di sini saya membandingkan tiga contoh (kelas adalah tipe referensi)
sumber
isEqual:
di Swift:override func isEqual(_ object: Any?) -> Bool {}
Ada seluk-beluk dengan Swift
===
yang melampaui aritmatika pointer saja. Sementara di Objective-C Anda dapat membandingkan dua pointer (yaituNSObject *
) dengan==
ini tidak lagi benar di Swift karena jenis memainkan peran yang jauh lebih besar selama kompilasi.Taman Bermain akan memberi Anda
Dengan string, kita harus terbiasa dengan ini:
tapi kemudian Anda juga bisa bersenang-senang sebagai berikut:
Saya yakin Anda bisa memikirkan lebih banyak lagi kasus lucu :-)
Pembaruan untuk Swift 3 (seperti yang disarankan oleh komentar dari Jakub Truhlář)
Ini terlihat sedikit lebih konsisten dengan
Type 'Int' does not conform to protocol 'AnyObject'
, namun kita dapatkantetapi konversi eksplisit membuat jelas bahwa mungkin ada sesuatu yang terjadi. Di sisi String hal-hal
NSString
masih akan tersedia selama kitaimport Cocoa
. Maka kita akan punyaMasih membingungkan untuk memiliki dua kelas String, tetapi menjatuhkan konversi implisit mungkin akan membuatnya sedikit lebih gamblang.
sumber
===
operator untuk membandingkanInts
. Not in Swift 3.===
tidak ada artinya untuk struct karena mereka tipe nilai. Secara khusus, ada tiga jenis yang perlu Anda ingat: tipe literal, seperti 1 atau "foo", yang belum terikat ke variabel dan biasanya hanya mempengaruhi kompilasi karena Anda biasanya tidak berurusan dengan mereka selama runtime; tipe struct sepertiInt
danString
mana yang Anda dapatkan ketika Anda menetapkan literal ke variabel, dan kelas-kelas sepertiAnyObject
danNSString
.Misalnya, jika Anda membuat dua instance kelas misalnya
myClass
:Anda dapat membandingkan contoh-contoh itu,
dikutip:
Kutipan dari: Apple Inc. “Bahasa Pemrograman Swift.” iBooks. https://itun.es/sk/jEUH0.l
sumber
Dalam Swift kita memiliki simbol === yang berarti kedua objek merujuk ke referensi yang sama dengan alamat yang sama
sumber
Hanya kontribusi kecil terkait
Any
objek.Saya bekerja dengan unit test sekitar
NotificationCenter
, yang menggunakanAny
parameter yang ingin saya bandingkan untuk kesetaraan.Namun, karena
Any
tidak dapat digunakan dalam operasi kesetaraan, perlu untuk mengubahnya. Pada akhirnya, saya memutuskan pada pendekatan berikut, yang memungkinkan saya untuk mendapatkan kesetaraan dalam situasi khusus saya, ditunjukkan di sini dengan contoh sederhana:Fungsi ini memanfaatkan ObjectIdentifier , yang menyediakan alamat unik untuk objek, memungkinkan saya untuk menguji.
Satu item yang perlu diperhatikan
ObjectIdentifier
per Apple di tautan di atas:sumber
==
digunakan untuk memeriksa apakah dua variabel yaitu sama2 == 2
. Tetapi dalam kasus===
itu berdiri untuk kesetaraan yaitu jika dua contoh merujuk ke contoh objek yang sama dalam kasus kelas referensi dibuat yang dipegang oleh banyak contoh lainnya.sumber
Swift 4: Contoh lain menggunakan Tes Unit yang hanya bekerja dengan ===
Catatan: Tes di bawah ini gagal dengan ==, berfungsi dengan ===
Dan kelasnya adalah
Kesalahan dalam Tes Unit jika Anda menggunakan == adalah,
Binary operator '==' cannot be applied to operands of type 'UITextFieldDelegate?' and 'ViewControllerUnderTest!'
sumber