Apa perbedaan antara ==
dan .equals()
dalam Scala, dan kapan menggunakannya?
Apakah implementasinya sama dengan di Jawa?
EDIT: Pertanyaan terkait berbicara tentang kasus spesifik AnyVal
. Kasus yang lebih umum adalah Any
.
Apa perbedaan antara ==
dan .equals()
dalam Scala, dan kapan menggunakannya?
Apakah implementasinya sama dengan di Jawa?
EDIT: Pertanyaan terkait berbicara tentang kasus spesifik AnyVal
. Kasus yang lebih umum adalah Any
.
Jawaban:
Anda biasanya menggunakan ==
, itu rute ke equals
, kecuali itu memperlakukan null
dengan benar. Referensi kesetaraan (jarang digunakan) adalah eq
.
3 == BigInt(3)
dan BigInt(3) == 3
itu benar. Tapi, 3.equals(BigInt(3))
itu salah, padahal BigInt(3).equals(3)
itu benar. Karena itu, lebih suka menggunakan ==
. Hindari penggunaan equals()
dalam skala. Saya pikir ==
melakukan konversi tersirat dengan baik, tetapi equals()
tidak.
new java.lang.Integer(1) == new java.lang.Double(1.0)
benar sementara new java.lang.Integer(1) equals new java.lang.Double(1.0)
itu salah?
equals
metode untuk membandingkan konten setiap instance. Ini adalah equals
metode yang sama yang digunakan di Jawa==
operator untuk membandingkan, tanpa khawatir tentang null
referensieq
metode untuk memeriksa apakah kedua argumen tersebut PERSIS referensi yang sama. Dianjurkan untuk tidak menggunakan kecuali Anda mengerti bagaimana ini bekerja dan sering equals
akan bekerja untuk apa yang Anda butuhkan. Dan pastikan untuk hanya menggunakan ini dengan AnyRef
argumen, bukan hanyaAny
CATATAN: Pada kasus equals
, seperti halnya di Jawa, ini mungkin tidak mengembalikan hasil yang sama jika Anda mengganti argumen mis. 1.equals(BigInt(1))
Akan mengembalikan false
tempat invers akan kembali true
. Ini karena setiap implementasi hanya memeriksa jenis tertentu. Bilangan primitif tidak memeriksa apakah argumen kedua adalah tipe Number
atau bukan BigInt
tetapi hanya tipe primitif lainnya
The AnyRef.equals(Any)
Metode adalah salah satu ditimpa oleh subclass. Metode dari Spesifikasi Java yang telah datang ke Scala juga. Jika digunakan pada instance unboxed, itu kotak untuk memanggil ini (meskipun tersembunyi di Scala; lebih jelas di Jawa dengan int
-> Integer
). Implementasi default hanya membandingkan referensi (seperti di Jawa)
The Any.==(Any)
Metode membandingkan dua benda dan memungkinkan argumen baik untuk menjadi nol (seolah-olah memanggil metode statis dengan dua contoh). Ini membandingkan jika keduanya null
, maka itu memanggil equals(Any)
metode pada contoh kotak.
The AnyRef.eq(AnyRef)
Metode membandingkan hanya referensi, yang mana contoh terletak di memori. Tidak ada tinju tersirat untuk metode ini.
1 equals 2
akan kembali false
, karena dialihkan keInteger.equals(...)
1 == 2
akan kembali false
, karena dialihkan keInteger.equals(...)
1 eq 2
tidak akan dikompilasi, karena kedua argumen harus bertipe AnyRef
new ArrayList() equals new ArrayList()
akan kembali true
, karena memeriksa kontennew ArrayList() == new ArrayList()
akan kembali true
, karena dialihkan keequals(...)
new ArrayList() eq new ArrayList()
akan kembali false
, karena kedua argumen adalah contoh yang berbedafoo equals foo
akan kembali true
, kecuali foo
adalah null
, maka akan melemparNullPointerException
foo == foo
akan kembali true
, bahkan jika foo
adanull
foo eq foo
akan kembali true
, karena kedua argumen terhubung ke referensi yang samaAda perbedaan yang menarik antara ==
dan equals
untuk Float
dan Double
jenis: Mereka memperlakukan secara NaN
berbeda:
scala> Double.NaN == Double.NaN
res3: Boolean = false
scala> Double.NaN equals Double.NaN
res4: Boolean = true
Sunting: Seperti yang ditunjukkan dalam komentar - "ini juga terjadi di Jawa" - tergantung pada apa tepatnya ini :
public static void main(final String... args) {
final double unboxedNaN = Double.NaN;
final Double boxedNaN = Double.valueOf(Double.NaN);
System.out.println(unboxedNaN == unboxedNaN);
System.out.println(boxedNaN == boxedNaN);
System.out.println(boxedNaN.equals(boxedNaN));
}
Ini akan dicetak
false
true
true
Jadi, unboxedNan
hasilnya false
ketika dibandingkan untuk kesetaraan karena ini adalah bagaimana angka-angka floating point IEEE mendefinisikannya dan ini harus benar-benar terjadi di setiap bahasa pemrograman (meskipun entah bagaimana mengacaukan gagasan identitas).
Kotak NaN menghasilkan true untuk perbandingan menggunakan ==
di Jawa karena kami membandingkan referensi objek.
Saya tidak punya penjelasan untuk equals
kasus ini, IMHO itu benar-benar harus berperilaku sama seperti ==
pada nilai ganda tanpa kotak, tetapi tidak.
Diterjemahkan ke Scala masalah ini sedikit lebih rumit karena Scala telah menyatukan jenis objek primitif dan menjadi Any
dan menerjemahkan ke dalam primitif ganda dan kotak ganda yang diperlukan. Dengan demikian scala ==
tampaknya bermuara pada perbandingan NaN
nilai-nilai primitif tetapi equals
menggunakan yang didefinisikan pada nilai ganda kotak (ada banyak sihir konversi implisit yang terjadi dan ada hal-hal yang di gandakan menjadi ganda oleh RichDouble
).
Jika Anda benar-benar perlu mencari tahu apakah sesuatu benar-benar NaN
digunakan isNaN
:
Dalam Scala == pertama periksa nilai Null dan kemudian memanggil metode sama dengan objek pertama