Saya memiliki pertanyaan tentang penggunaan sakelar untuk instanceof
objek:
Sebagai contoh: masalah saya dapat direproduksi di Jawa:
if(this instanceof A)
doA();
else if(this instanceof B)
doB();
else if(this instanceof C)
doC():
Bagaimana itu diterapkan menggunakan switch...case
?
java
switch-statement
instanceof
olidev
sumber
sumber
Jawaban:
Ini adalah skenario khas di mana subtipe polimorfisme membantu. Lakukan hal berikut
Maka Anda hanya dapat memanggil
do()
padathis
.Jika Anda tidak bebas untuk mengubah
A
,B
danC
, Anda bisa menerapkan pola pengunjung untuk mencapai yang sama.sumber
jika Anda benar-benar tidak bisa membuat kode ke antarmuka, maka Anda bisa menggunakan enum sebagai perantara:
sumber
Cukup buat Peta di mana kelas adalah kuncinya dan fungsinya, yaitu lambda atau sejenisnya, adalah nilainya.
// tentu saja, perbaiki ini hanya untuk menginisialisasi sekali
Jika Anda perlu memeriksa Pengecualian daripada mengimplementasikan FunctionalInterface yang melempar Pengecualian dan gunakan itu alih-alih Runnable.
sumber
instanceof
, dan tidak, skenario saya sayangnya bukan salah satu dari mereka yang mudah masuk ke dalam kotak itu ...)Untuk jaga-jaga jika seseorang akan membacanya:
Solusi TERBAIK di java adalah:
Manfaat BESAR dari pola tersebut adalah:
Anda cukup melakukannya (TIDAK ADA saklar sama sekali):
Jika Anda menambahkan Aksi baru yang disebut "d", Anda HARUS menerapkan metode doAction (...)
CATATAN: Pola ini dijelaskan dalam Joshua's Bloch "Java Efektif (Edisi 2)"
sumber
@Override
diperlukan di atas setiap implementasidoAction()
?action
akan digunakan? Dengan contoh luar kaskade yang memanggilsomeFunction()
dengan yang benaraction
? Ini hanya menambah tingkat tipuan lainnya.Kamu tidak bisa The
switch
pernyataan hanya dapat berisicase
pernyataan yang konstanta waktu kompilasi dan yang mengevaluasi ke integer (Sampai dengan Java 6 dan string di Jawa 7).Apa yang Anda cari disebut "pencocokan pola" dalam pemrograman fungsional.
Lihat juga Menghindari contoh di Jawa
sumber
Sebagaimana dibahas dalam jawaban teratas, pendekatan OOP tradisional adalah menggunakan polimorfisme alih-alih beralih. Bahkan ada pola refactoring yang terdokumentasi dengan baik untuk trik ini: Ganti Kondisional dengan Polimorfisme . Setiap kali saya meraih pendekatan ini, saya juga ingin mengimplementasikan objek Null untuk memberikan perilaku default.
Dimulai dengan Java 8, kita bisa menggunakan lambdas dan generik untuk memberi kita sesuatu yang programmer sangat akrab dengan: pencocokan pola. Ini bukan fitur bahasa inti tetapi perpustakaan Javaslang menyediakan satu implementasi. Contoh dari javadoc :
Ini bukan paradigma paling alami di dunia Jawa jadi gunakan dengan hati-hati. Sementara metode generik akan menyelamatkan Anda dari keharusan mengetikkan nilai yang cocok, kami kehilangan cara standar untuk menguraikan objek yang cocok seperti dengan kelas kasus Scala misalnya.
sumber
Saya tahu ini sangat terlambat tetapi bagi pembaca di masa depan ...
Waspadalah terhadap pendekatan di atas yang hanya didasarkan pada nama kelas A , B , C ...:
Kecuali jika Anda dapat menjamin bahwa A , B , C ... (semua subclass atau pelaksana Basis ) final, maka subclass dari A , B , C ... tidak akan ditangani.
Meskipun pendekatan if, elseif, elseif .. lebih lambat untuk sejumlah besar subclass / pelaksana, itu lebih akurat.
sumber
Sayangnya, tidak mungkin keluar dari kotak karena pernyataan switch-case mengharapkan ekspresi yang konstan. Untuk mengatasinya, salah satu caranya adalah dengan menggunakan nilai enum dengan nama kelas mis
Dengan itu dimungkinkan untuk menggunakan pernyataan switch seperti ini
sumber
Tidak, tidak ada cara untuk melakukan ini. Namun yang mungkin ingin Anda lakukan adalah mempertimbangkan Polimorfisme sebagai cara untuk menangani masalah semacam ini.
sumber
Menggunakan pernyataan switch seperti ini bukan cara berorientasi objek. Anda sebaiknya menggunakan kekuatan polimorfisme . Cukup tulis
Setelah sebelumnya membuat kelas dasar:
yang merupakan kelas dasar untuk
A
,B
danC
:sumber
Ini akan bekerja lebih cepat dan masuk akal jika
- Anda memiliki banyak 'kasus'
- proses dieksekusi dalam konteks sensitif kinerja
sumber
Anda tidak dapat beralih hanya bekerja dengan byte, pendek, char, int, String dan jenis enumerated (dan versi objek primitif, itu juga tergantung pada versi java Anda, String dapat
switch
diedit di dalam java 7)sumber
Saya pribadi suka kode Java 1.8 berikut:
Akan menghasilkan:
Kode sampel menggunakan Strings tetapi Anda dapat menggunakan jenis objek apa pun, termasuk Kelas. misalnya
.myCase(this.getClass(), (o) -> ...
Perlu cuplikan berikut:
sumber
Java sekarang memungkinkan Anda untuk beralih dengan cara OP. Mereka menyebutnya Pencocokan Pola untuk sakelar. Saat ini sedang dalam Rancangan tetapi melihat berapa banyak pekerjaan yang telah mereka masukkan ke switch baru-baru ini saya pikir itu akan melalui. Contoh yang diberikan dalam JEP adalah
atau menggunakan sintaks lambda mereka dan mengembalikan nilai
bagaimanapun mereka telah melakukan hal-hal keren dengan sakelar.
sumber
Jika Anda dapat memanipulasi antarmuka umum, Anda bisa menambahkan enum dan meminta setiap kelas mengembalikan nilai unik. Anda tidak memerlukan instanceof atau pola pengunjung.
Bagi saya, logika perlu ditulis dalam pernyataan switch, bukan objek itu sendiri. Ini solusi saya:
ClassA, ClassB, and ClassC implement CommonClass
Antarmuka:
Enum:
Implan:
Jika Anda menggunakan java 7, Anda bisa meletakkan nilai string untuk enum dan blok kasus sakelar akan tetap berfungsi.
sumber
value
lapangan berlebihan jika Anda hanya ingin membedakan konstanta enum - Anda dapat menggunakan konstanta secara langsung (seperti yang Anda lakukan).Bagaimana dengan ini ?
sumber
this.getSimpleName()
Tidak yakin apakah poster itu bingung dengan JS (ya, dia menggunakan konsol, hehe).Saya pikir ada alasan untuk menggunakan pernyataan switch. Jika Anda menggunakan xText, kode yang dihasilkan mungkin. Atau jenis lain dari kelas yang dihasilkan EMF.
mengembalikan sebuah String dari Nama Implementasi Kelas. yaitu: org.eclipse.emf.ecore.util.EcoreUtil
mengembalikan representasi sederhana yaitu: EcoreUtil
sumber
switch
sebagaicase
kondisi karena tidak nilai konstanJika Anda perlu "beralih" melalui tipe objek "ini" kelas ini, jawaban ini adalah yang terbaik https://stackoverflow.com/a/5579385/2078368
Tetapi jika Anda perlu menerapkan "beralih" ke variabel lain. Saya akan menyarankan solusi lain. Tetapkan antarmuka berikut:
Terapkan antarmuka ini di setiap kelas yang Anda ingin "beralih". Contoh:
Setelah itu Anda bisa menggunakannya dengan cara berikut:
Satu-satunya hal yang harus Anda perhatikan - pertahankan "tipe" unik di semua kelas yang mengimplementasikan ClassTypeInterface. Ini bukan masalah besar, karena jika ada persimpangan Anda menerima kesalahan waktu kompilasi untuk pernyataan "sakelar kasus".
sumber
TYPE
, Anda dapat menggunakan enum dan keunikan dijamin (seperti yang dilakukan dalam jawaban ini ). Namun, dengan salah satu pendekatan yang Anda harus refactor di dua tempat ketika Anda mengganti nama.TYPE = "A"
saat penggantian nama. Terutama jika itu di luar kelas yang sesuai, orang mungkin juga lupa ketika melakukannya secara manual. IntelliJ sebenarnya juga menemukan kemunculan nama kelas dalam string atau komentar tetapi itu hanya pencarian teks (alih-alih melihat pohon sintaks) dan dengan demikian menyertakan false positive.Berikut cara fungsional untuk menyelesaikannya di Java 8 menggunakan http://www.vavr.io/
sumber
Meskipun tidak mungkin untuk menulis pernyataan switch, dimungkinkan untuk bercabang ke pemrosesan spesifik untuk setiap jenis yang diberikan. Salah satu cara untuk melakukan ini adalah dengan menggunakan mekanisme pengiriman ganda standar. Contoh di mana kita ingin "beralih" berdasarkan tipe adalah Jersey Exception mapper di mana kita perlu memetakan banyak pengecualian untuk respons kesalahan. Sementara untuk kasus khusus ini mungkin ada cara yang lebih baik (yaitu menggunakan metode polimorfik yang menerjemahkan setiap pengecualian ke respons kesalahan), menggunakan mekanisme pengiriman ganda masih berguna dan praktis.
Maka di mana pun "saklar" dibutuhkan, Anda dapat melakukannya sebagai berikut:
sumber
Buat Enum dengan nama Kelas.
Temukan nama kelas objek. Tulis kotak saklar di atas enum.
Semoga ini membantu.
sumber
Kerangka Pemodelan Eclipse memiliki ide menarik yang juga mempertimbangkan warisan. Konsep dasar didefinisikan dalam antarmuka Switch : switching dilakukan dengan memanggil metode doSwitch .
Yang benar-benar menarik adalah implementasinya. Untuk setiap jenis bunga, a
Metode harus diimplementasikan (dengan implementasi standar mengembalikan nol). The doSwitch implementasi akan mencoba untuk memanggil al caseXXX metode pada objek untuk semua jenis hirarki-nya. Sesuatu di baris:
Kerangka kerja yang sebenarnya menggunakan id integer untuk setiap kelas, jadi logikanya sebenarnya adalah saklar murni:
Anda dapat melihat implementasi lengkap ECoreSwitch untuk mendapatkan ide yang lebih baik.
sumber
bahkan ada cara yang lebih sederhana untuk meniru struktur saklar yang menggunakan instanceof, Anda melakukan ini dengan membuat blok kode dalam metode Anda dan menamainya dengan label. Kemudian Anda menggunakan struktur jika untuk meniru pernyataan kasus. Jika kasing benar maka Anda menggunakan break LABEL_NAME untuk keluar dari struktur sakelar sementara Anda.
sumber
if
...else if
kode yang diberikan oleh OP?if
...else if
dengan pernyataan "goto", yang merupakan cara yang salah untuk menerapkan aliran kontrol dalam bahasa seperti Java.