Saya telah membaca artikel ini: Cara Menulis Metode Kesetaraan di Jawa .
Pada dasarnya, ini memberikan solusi untuk metode equals () yang mendukung warisan:
Point2D twoD = new Point2D(10, 20);
Point3D threeD = new Point3D(10, 20, 50);
twoD.equals(threeD); // true
threeD.equals(twoD); // true
Tapi apakah itu ide yang bagus? dua contoh ini tampaknya sama tetapi mungkin memiliki dua kode hash yang berbeda. Bukankah itu agak salah?
Saya percaya ini akan lebih baik dicapai dengan casting operan saja.
java
c#
scala
comparison
Wes
sumber
sumber
z
koordinat nol mungkin merupakan konvensi yang berguna untuk beberapa aplikasi (sistem CAD awal yang menangani data lama datang ke pikiran). Tapi itu adalah konvensi yang sewenang-wenang. Pesawat dalam ruang dengan 3 dimensi atau lebih dapat memiliki orientasi sewenang-wenang ... itulah yang membuat masalah menarik menjadi menarik.Jawaban:
Ini tidak boleh sama karena merusak transitivitas . Pertimbangkan dua ungkapan ini:
Karena persamaan adalah transitif, ini harus berarti bahwa ungkapan berikut ini juga benar:
Tapi tentu saja - tidak.
Jadi, ide casting Anda benar - berharap bahwa di Jawa, casting berarti casting jenis referensi. Yang Anda inginkan di sini adalah metode konversi yang akan membuat
Point2D
objek baru dariPoint3D
objek. Ini juga akan membuat ekspresi lebih bermakna:sumber
(10, 20, 50)
sederajat(10, 20, 60)
baik-baik saja. Kami hanya peduli10
dan20
.Point2D
adaprojectXYZ()
metode untuk memberikanPoint3D
representasi itu sendiri? Dengan kata lain, haruskah implementasi saling kenal?Point2D
tampaknya lebih sederhana karena memproyeksikan poin 2D memerlukan mendefinisikan pesawat mereka dalam ruang 3D terlebih dahulu. Jika titik 2D tahu itu pesawat, maka itu sudah menjadi titik 3D. Jika tidak, itu tidak dapat diproyeksikan. Saya teringat akan Abbott's Flatland .Plane3D
objek, yang akan mendefinisikan pesawat dalam ruang 3D, bahwa pesawat dapat memilikilift
metode (2D-> 3D mengangkat, bukan memproyeksikan) yang akan menerimaPoint2D
dan nomor untuk "sumbu ketiga "- jarak dari pesawat di sepanjang pesawat normal. Untuk kemudahan penggunaan, Anda dapat mendefinisikan bidang umum sebagai konstanta statis, sehingga Anda dapat melakukan hal-hal sepertiPlane3D.XY.lift(new Point2D(10, 20), 50).equals(new Point3D(10, 20, 50))
Saya berjalan pergi dari membaca artikel berpikir tentang kebijaksanaan Alan J. Perlis:
Fakta bahwa mendapatkan "kesetaraan" dengan benar adalah jenis masalah yang membuat Martin Ordersky penemu Scala di malam hari harus memberi jeda tentang apakah mengesampingkan
equals
pohon warisan adalah ide yang bagus.Apa yang terjadi ketika kita kurang beruntung untuk mendapatkannya
ColoredPoint
adalah geometri kita gagal karena kita menggunakan pewarisan untuk memperbanyak tipe data daripada membuat yang bagus. Ini meskipun harus kembali dan memodifikasi simpul akar pohon warisan untuk membuatequals
pekerjaan. Mengapa tidak hanya menambahkanz
dancolor
kePoint
?Alasan yang baik akan melakukannya
Point
danColoredPoint
beroperasi di domain yang berbeda ... setidaknya jika domain tersebut tidak pernah berbaur. Namun jika itu masalahnya, kita tidak perlu menimpanyaequals
. MembandingkanColoredPoint
danPoint
untuk kesetaraan hanya masuk akal di domain ketiga tempat mereka diizinkan untuk bergaul. Dan dalam hal itu, mungkin lebih baik untuk memiliki "kesetaraan" yang disesuaikan dengan domain ketiga daripada mencoba menerapkan semantik kesetaraan dari satu atau yang lain atau keduanya dari domain yang tidak tergulung. Dengan kata lain "kesetaraan" harus didefinisikan secara lokal ke tempat di mana kita memiliki lumpur yang mengalir dari kedua sisi karena kita mungkin tidak inginColoredPoint.equals(pt)
gagal melawan contoh-contohPoint
bahkan jika penulisColoredPoint
berpendapat itu adalah ide yang baik enam bulan lalu pada jam 2 pagi .sumber
Ketika dewa pemrograman lama menciptakan pemrograman berorientasi objek dengan kelas, mereka memutuskan ketika datang ke komposisi dan pewarisan untuk memiliki dua hubungan untuk objek: "adalah" dan "memiliki".
Ini sebagian memecahkan masalah subclass yang berbeda dari kelas induk tetapi membuatnya dapat digunakan tanpa melanggar kode. Karena turunan subclass "adalah" objek superclass dan dapat diganti secara langsung untuk itu, meskipun subclass memiliki lebih banyak fungsi anggota atau anggota data, "memiliki" menjamin bahwa ia akan melakukan semua fungsi induk dan memiliki semua anggota Jadi Anda bisa mengatakan Point3D "adalah" Point, dan Point2D "adalah" Point jika keduanya mewarisi dari Point. Selain itu Point3D bisa menjadi subclass dari Point2D.
Namun, kesetaraan antar kelas adalah masalah khusus domain, dan contoh di atas tidak jelas untuk apa yang dibutuhkan oleh programmer agar program dapat bekerja dengan benar. Secara umum, aturan domain-matematika diikuti dan nilai-nilai data akan menghasilkan kesetaraan jika Anda membatasi ruang lingkup perbandingan hanya dalam kasus ini dua dimensi, tetapi tidak jika Anda membandingkan semua anggota data.
Jadi Anda mendapatkan tabel persamaan penyempitan:
Anda biasanya memilih aturan yang paling ketat yang Anda bisa yang masih akan melakukan semua fungsi yang diperlukan dalam domain masalah Anda. Tes kesetaraan bawaan untuk angka dirancang sedemikian ketatnya untuk tujuan matematika, tetapi pemrogram memiliki banyak cara untuk mengatasinya jika itu bukan tujuannya, termasuk pembulatan ke atas / ke bawah, pemotongan, gt, lt, dll. . Objek dengan cap waktu sering dibandingkan dengan waktu pembuatannya sehingga setiap instance harus unik sehingga perbandingan menjadi sangat spesifik.
Faktor desain dalam hal ini adalah untuk menentukan cara yang efisien untuk membandingkan objek. Kadang-kadang perbandingan rekursif semua anggota objek data adalah apa yang harus Anda lakukan, dan itu bisa menjadi sangat mahal jika Anda memiliki banyak dan banyak objek dengan banyak anggota data. Alternatif adalah dengan hanya membandingkan nilai data yang relevan, atau memiliki objek menghasilkan nilai hash anggota data yang bersangkutan untuk perbandingan cepat dengan objek serupa lainnya, menjaga koleksi diurutkan dan dipangkas untuk membuat perbandingan lebih cepat dan kurang intensif cpu, dan mungkin memungkinkan objek yang identik dalam data yang akan diambil dan pointer duplikat ke objek tunggal diletakkan di tempatnya.
sumber
Aturannya adalah, setiap kali Anda menimpa
hashcode()
, Anda menimpaequals()
, dan sebaliknya. Apakah ini ide yang baik atau tidak tergantung pada penggunaan yang dimaksudkan. Secara pribadi, saya akan menggunakan metode yang berbeda (isLike()
atau serupa) untuk mencapai efek yang sama.sumber
Seringkali berguna bagi kelas yang tidak menghadap ke publik untuk memiliki metode pengujian ekivalensi yang memungkinkan objek dari tipe yang berbeda untuk mempertimbangkan satu sama lain "sama" jika mereka mewakili informasi yang sama, tetapi karena Java tidak memungkinkan sarana yang kelasnya dapat meniru masing-masing lain itu sering baik untuk memiliki satu jenis pembungkus menghadap publik dalam kasus-kasus di mana dimungkinkan untuk memiliki objek yang setara dengan representasi yang berbeda.
Sebagai contoh, pertimbangkan kelas yang merangkum matriks
double
nilai 2D yang tidak dapat diubah . Jika satu metode luar meminta matriks identitas ukuran 1000, yang kedua meminta matriks diagonal dan melewati array yang berisi 1000 yang, dan yang ketiga meminta matriks 2D dan melewati array 1000x1000 di mana elemen pada diagonal primer semuanya 1,0 dan semua yang lain adalah nol, objek yang diberikan kepada ketiga kelas dapat menggunakan backing store yang berbeda secara internal [yang pertama memiliki bidang tunggal untuk ukuran, yang kedua memiliki array ribuan elemen, dan yang ketiga memiliki array array 1000 elemen] tetapi harus melaporkan satu sama lain sebagai setara [karena ketiganya merangkum matriks tetap 1000x1000 dengan yang ada di diagonal dan nol di tempat lain].Selain fakta bahwa ia menyembunyikan keberadaan jenis-jenis backing-store yang berbeda, pembungkus juga akan berguna untuk memfasilitasi perbandingan, karena memeriksa item untuk kesetaraan pada umumnya akan menjadi proses multi-langkah. Tanyakan item pertama apakah itu tahu apakah itu sama dengan item kedua; jika tidak tahu, tanyakan yang kedua apakah tahu apakah itu sama dengan yang pertama. Jika tidak ada objek yang tahu, maka tanyakan setiap array tentang konten elemen individualnya [orang mungkin menambahkan pemeriksaan lain sebelum memutuskan untuk melakukan rute perbandingan item-individu yang sangat lambat].
Perhatikan bahwa metode uji ekivalensi untuk setiap objek dalam skenario ini perlu mengembalikan nilai tiga-negara ("Ya, saya setara", "Tidak, saya tidak setara", atau "Saya tidak tahu"), jadi metode "sama dengan" yang normal tidak akan cocok. Sementara objek apa pun dapat dengan mudah menjawab "Saya tidak tahu" ketika ditanya tentang yang lain, menambahkan logika untuk misalnya matriks diagonal yang tidak akan repot bertanya matriks identitas atau matriks diagonal tentang elemen apa pun di luar diagonal utama akan sangat mempercepat perbandingan di antara objek tersebut. jenis.
sumber