Saya mencoba memahami perbedaan antara keempat metode ini. Saya tahu secara default yang ==
memanggil metode equal?
yang mengembalikan true ketika kedua operan merujuk ke objek yang sama persis.
===
secara default juga memanggil panggilan ==
mana equal?
... oke, jadi jika ketiga metode ini tidak diganti, maka saya kira
===
, ==
dan equal?
melakukan hal yang persis sama?
Sekarang tiba eql?
. Apa yang dilakukan ini (secara default)? Apakah itu membuat panggilan ke hash / id operan?
Mengapa Ruby memiliki begitu banyak tanda kesetaraan? Apakah mereka seharusnya berbeda dalam semantik?
ruby
comparison
operators
equality
denniss
sumber
sumber
"a" == "a"
,"a" === "a"
dan"a".eql? "a"
. Tapi ini salah:"a".equal? "a"
(Milik saya ruby 1.9.2-p180)a = Object.new; b = Object.new
maka semua==
,===
,.equal?
,.eql?
akan kembalitrue
untuka
vsa
dan palsu untuka
vsb
.Jawaban:
Saya akan sangat mengutip dokumentasi Obyek di sini, karena saya pikir ia memiliki beberapa penjelasan yang bagus. Saya mendorong Anda untuk membacanya, dan juga dokumentasi untuk metode ini karena mereka ditimpa di kelas lain, seperti String .
Catatan: jika Anda ingin mencobanya sendiri pada objek yang berbeda, gunakan sesuatu seperti ini:
==
- "kesetaraan" generikIni adalah perbandingan yang paling umum, dan dengan demikian tempat paling mendasar di mana Anda (sebagai penulis kelas) dapat memutuskan apakah dua objek "sama" atau tidak.
===
- kesetaraan kasusIni sangat berguna. Contoh hal-hal yang memiliki
===
implementasi yang menarik :Jadi Anda dapat melakukan hal-hal seperti:
Lihat jawaban saya di sini untuk contoh rapi tentang bagaimana
case
+Regex
dapat membuat kode lebih bersih. Dan tentu saja, dengan menyediakan===
implementasi Anda sendiri , Anda bisa mendapatkancase
semantik khusus .eql?
-Hash
kesetaraanJadi Anda bebas untuk menimpa ini untuk penggunaan Anda sendiri, atau Anda dapat menimpa
==
dan menggunakanalias :eql? :==
sehingga kedua metode berperilaku dengan cara yang sama.equal?
- perbandingan identitasIni adalah perbandingan pointer secara efektif.
sumber
Numeric
menanganinya lebih ketat daripada==
. Itu benar-benar terserah penulis kelas.===
jarang digunakan di luarcase
pernyataan.===
sebagai "cocok" (kira-kira). Seperti pada, "apakah regexp cocok dengan string" atau "apakah rentang cocok dengan (termasuk) nomor".Saya suka jawaban jtbandes, tetapi karena cukup panjang, saya akan menambahkan jawaban ringkas saya sendiri:
==
,===
,eql?
,equal?
4 pembanding, yaitu. 4 cara membandingkan 2 objek, di Ruby.
Karena, di Ruby, semua pembanding (dan sebagian besar operator) sebenarnya adalah pemanggilan metode, Anda dapat mengubah, menimpa, dan menentukan sendiri semantik dari metode perbandingan ini. Namun, penting untuk dipahami, ketika bahasa internal Ruby menggunakan pembanding:
==
(perbandingan nilai)Ruby menggunakan: == di mana-mana untuk membandingkan nilai 2 objek, mis. Nilai hash:
===
(perbandingan kasus)Ruby menggunakan: === dalam kasus / saat konstruksi. Cuplikan kode berikut identik secara logis:
eql?
(Perbandingan hash-kunci)Ruby menggunakan: eql? (dalam kombinasi dengan metode hash) untuk membandingkan kunci hash. Di sebagian besar kelas: eql? identik dengan: ==.
Pengetahuan tentang: eql? hanya penting, ketika Anda ingin membuat kelas khusus Anda sendiri:
Catatan: Set kelas Ruby yang umum digunakan juga bergantung pada perbandingan tombol-Hash.
equal?
(perbandingan identitas objek)Ruby menggunakan: sama? untuk memeriksa apakah dua objek identik. Metode ini (dari kelas BasicObject) tidak seharusnya ditimpa.
sumber
eql?
sangat menyesatkan.eql?
adalah perbandingan kesetaraan yang konsisten dengan bagaimana hash dihitung, yaitua.eql?(b)
menjamin itua.hash == b.hash
. Itu tidak hanya membandingkan kode hash.bar === foo
dan tidakfoo === bar
? Saya berharap yang terakhir ini benar dan ini penting karena kompiler memanggil sisi kiri: === `'bar === foo
: Ruby menggunakan nilai case di sisi kiri dan variabel case di sisi kanan. Ini mungkin ada hubungannya dengan menghindari NPE (Null Pointer Exception).Operator kesetaraan: == dan! =
Operator ==, juga dikenal sebagai kesetaraan atau dobel sama, akan mengembalikan true jika kedua objek sama dan salah jika tidak.
Operator! =, Juga dikenal sebagai ketimpangan, adalah kebalikan dari ==. Ini akan mengembalikan true jika kedua objek tidak sama dan salah jika keduanya sama.
Perhatikan bahwa dua array dengan elemen yang sama dalam urutan yang berbeda tidak sama, versi huruf besar dan kecil dari huruf yang sama tidak sama dan seterusnya.
Saat membandingkan angka dari tipe yang berbeda (mis. Integer dan float), jika nilai numeriknya sama, == akan mengembalikan true.
sama?
Tidak seperti operator == yang menguji apakah kedua operan sama, metode yang sama memeriksa apakah kedua operan merujuk ke objek yang sama. Ini adalah bentuk kesetaraan paling ketat di Ruby.
Contoh: a = "zen" b = "zen"
Dalam contoh di atas, kami memiliki dua string dengan nilai yang sama. Namun, mereka adalah dua objek yang berbeda, dengan ID objek yang berbeda. Jadi, sama saja? metode akan mengembalikan false.
Mari kita coba lagi, hanya saja kali ini b akan menjadi referensi ke a. Perhatikan bahwa ID objek sama untuk kedua variabel, karena mereka menunjuk ke objek yang sama.
EQL?
Di kelas Hash, persamaannya? Metode ini digunakan untuk menguji kunci untuk kesetaraan. Diperlukan latar belakang untuk menjelaskan hal ini. Dalam konteks umum komputasi, fungsi hash mengambil string (atau file) dari ukuran apa pun dan menghasilkan string atau integer ukuran tetap yang disebut kode hash, biasanya disebut sebagai hash saja. Beberapa jenis kode hash yang umum digunakan adalah MD5, SHA-1, dan CRC. Mereka digunakan dalam algoritma enkripsi, pengindeksan basis data, pemeriksaan integritas file, dll. Beberapa bahasa pemrograman, seperti Ruby, menyediakan jenis koleksi yang disebut tabel hash. Tabel hash adalah koleksi seperti kamus yang menyimpan data berpasangan, terdiri dari kunci unik dan nilainya. Di bawah tenda, kunci-kunci itu disimpan sebagai kode hash. Tabel hash biasanya disebut sebagai hash saja. Perhatikan bagaimana kata hash dapat merujuk ke kode hash atau tabel hash.
Ruby menyediakan metode bawaan yang disebut hash untuk menghasilkan kode hash. Pada contoh di bawah ini, dibutuhkan string dan mengembalikan kode hash. Perhatikan bagaimana string dengan nilai yang sama selalu memiliki kode hash yang sama, meskipun mereka adalah objek yang berbeda (dengan ID objek yang berbeda).
Metode hash diimplementasikan dalam modul Kernel, termasuk dalam kelas Object, yang merupakan root default dari semua objek Ruby. Beberapa kelas seperti Simbol dan Integer menggunakan implementasi default, yang lain seperti String dan Hash menyediakan implementasi mereka sendiri.
Di Ruby, ketika kita menyimpan sesuatu dalam hash (koleksi), objek yang disediakan sebagai kunci (misalnya, string atau simbol) dikonversi menjadi dan disimpan sebagai kode hash. Kemudian, ketika mengambil elemen dari hash (koleksi), kami menyediakan objek sebagai kunci, yang dikonversi menjadi kode hash dan dibandingkan dengan kunci yang ada. Jika ada kecocokan, nilai item yang sesuai dikembalikan. Perbandingan dibuat dengan menggunakan eql? metode di bawah tenda.
Dalam kebanyakan kasus, persamaannya? metode berperilaku serupa dengan metode ==. Namun, ada beberapa pengecualian. Misalnya, eql? tidak melakukan konversi tipe implisit ketika membandingkan integer dengan float.
Operator kesetaraan kasus: ===
Banyak kelas bawaan Ruby, seperti String, Range, dan Regexp, menyediakan implementasi mereka sendiri dari operator ===, juga dikenal sebagai kesetaraan kasus, sama dengan tiga atau tiga sama. Karena diimplementasikan secara berbeda di setiap kelas, ia akan berperilaku berbeda tergantung pada jenis objek yang dipanggil. Secara umum, ia mengembalikan true jika objek di sebelah kanan "milik" atau "adalah anggota" objek di sebelah kiri. Sebagai contoh, ini dapat digunakan untuk menguji apakah suatu objek adalah turunan dari kelas (atau salah satu dari subkelasnya).
Hasil yang sama dapat dicapai dengan metode lain yang mungkin paling cocok untuk pekerjaan itu. Biasanya lebih baik menulis kode yang mudah dibaca dengan menjadi sejelas mungkin, tanpa mengorbankan efisiensi dan keringkasan.
Perhatikan contoh terakhir yang dikembalikan false karena integer seperti 2 adalah instance dari kelas Fixnum, yang merupakan subkelas dari kelas Integer. ===, is_a? dan instance_of? Metode mengembalikan true jika objek adalah turunan dari kelas yang diberikan atau setiap subclass. Metode instance_of lebih ketat dan hanya mengembalikan true jika objek adalah turunan dari kelas yang tepat, bukan subkelas.
Is_a? dan kind_of? metode diimplementasikan dalam modul Kernel, yang dicampur oleh kelas Object. Keduanya alias dengan metode yang sama. Mari kita verifikasi:
Kernel.instance_method (: kind_of?) == Kernel.instance_method (: is_a?) # Output: => true
Rentang Implementasi ===
Ketika operator === dipanggil pada objek rentang, ia mengembalikan true jika nilai di sebelah kanan jatuh dalam rentang di sebelah kiri.
Ingat bahwa operator === memanggil metode === dari objek sebelah kiri. Jadi (1..4) === 3 setara dengan (1..4). === 3. Dengan kata lain, kelas operan kiri akan menentukan implementasi metode === yang akan menjadi dipanggil, sehingga posisi operan tidak dapat dipertukarkan.
Implementasi Regexp ===
Mengembalikan nilai true jika string di sebelah kanan cocok dengan ekspresi reguler di sebelah kiri. / zen / === "berlatih zazen hari ini" # Output: => true # sama dengan "berlatih zazen hari ini" = ~ / zen /
Penggunaan implisit operator === pada pernyataan case / when
Operator ini juga digunakan di bawah kap pada pernyataan kasus / saat. Itu adalah penggunaannya yang paling umum.
Dalam contoh di atas, jika Ruby secara implisit menggunakan operator ganda sama dengan (==), kisaran 10..20 tidak akan dianggap sama dengan bilangan bulat seperti 15. Mereka cocok karena operator sama dengan tiga (===) adalah secara implisit digunakan dalam semua kasus / kapan pernyataan. Kode dalam contoh di atas setara dengan:
Operator pencocokan pola: = ~ dan! ~
Operator = ~ (equal-tilde) dan! ~ (Bang-tilde) digunakan untuk mencocokkan string dan simbol dengan pola regex.
Implementasi metode = ~ di kelas String dan Simbol mengharapkan ekspresi reguler (turunan dari kelas Regexp) sebagai argumen.
Implementasi di kelas Regexp mengharapkan string atau simbol sebagai argumen.
Di semua implementasi, ketika string atau simbol cocok dengan pola Regexp, itu mengembalikan bilangan bulat yang merupakan posisi (indeks) dari pertandingan. Jika tidak ada kecocokan, mengembalikan nihil. Ingat bahwa, di Ruby, nilai integer apa pun adalah "benar" dan nil adalah "salah", sehingga operator = ~ dapat digunakan dalam pernyataan if dan operator ternary.
Operator pencocokan pola juga berguna untuk menulis pernyataan yang lebih pendek jika. Contoh:
Operator! ~ Adalah kebalikan dari = ~, ia mengembalikan true ketika tidak ada kecocokan dan salah jika ada kecocokan.
Info lebih lanjut tersedia di posting blog ini .
sumber
:zen === "zen"
mengembalikan falseRuby memaparkan beberapa metode berbeda untuk menangani kesetaraan:
Lanjutkan membaca dengan mengklik tautan di bawah, itu memberi saya pemahaman yang diringkas jelas.
Semoga ini bisa membantu orang lain.
sumber
=== # --- kesetaraan kasus
== # --- kesetaraan umum
keduanya bekerja serupa tetapi "===" bahkan melakukan pernyataan kasus
di sini bedanya
sumber
a==b
kemudiana===b
. Tetapia===b
jauh lebih kuat.===
tidak simetris, dana===b
berarti hal yang sangat berbedab===a
, apalagia==b
.Saya ingin memperluas
===
operator.===
bukan operator kesetaraan!Tidak.
Mari kita selesaikan hal itu.
Anda mungkin akrab dengan
===
sebagai operator kesetaraan dalam Javascript dan PHP, tetapi ini bukan operator kesetaraan di Ruby dan memiliki semantik yang berbeda secara fundamental.Jadi apa fungsinya
===
?===
adalah operator pencocokan pola!===
cocok dengan ekspresi reguler===
memeriksa rentang keanggotaan===
memeriksa menjadi instance dari sebuah kelas===
panggilan ekspresi lambda===
terkadang memeriksa kesetaraan, tetapi sebagian besar tidakJadi bagaimana kegilaan ini masuk akal?
Enumerable#grep
gunakan secara===
internalcase when
pernyataan digunakan secara===
internalrescue
gunakan secara===
internalItu sebabnya Anda bisa menggunakan ekspresi reguler dan kelas dan rentang dan bahkan ekspresi lambda dalam sebuah
case when
pernyataan.Beberapa contoh
Semua contoh ini juga berfungsi dengan baik
pattern === value
, serta dengangrep
metode.sumber
Saya menulis tes sederhana untuk semua hal di atas.
sumber