Enum tidak hanya harus mewakili set pasif (misalnya warna). Mereka dapat mewakili objek yang lebih kompleks dengan fungsionalitas, dan karenanya Anda mungkin ingin menambahkan fungsionalitas lebih lanjut untuk ini - misalnya Anda mungkin memiliki antarmuka seperti Printable, Reportabledll. Dan komponen yang mendukung ini.
Berikut adalah satu contoh (yang serupa / lebih baik ditemukan di Java Edisi 2 Efektif):
publicinterfaceOperator{int apply (int a,int b);}publicenumSimpleOperatorsimplementsOperator{
PLUS {int apply(int a,int b){return a + b;}},
MINUS {int apply(int a,int b){return a - b;}};}publicenumComplexOperatorsimplementsOperator{// can't think of an example right now :-/}
Sekarang untuk mendapatkan daftar Operator Sederhana + Kompleks:
Operator kompleks bisa menjadi "pow" dan sejenisnya.
Pimgd
2
Pertama kali melihat sintaks Enum (dengan kurung kurawal setelah anggota), dan saya sudah pemrograman dengan Java selama 6 tahun. TIL.
jrahhali
23
The Comparablecontoh yang diberikan oleh beberapa orang di sini yang salah, karena Enumsudah mengimplementasikan itu. Anda bahkan tidak bisa menimpanya.
Contoh yang lebih baik adalah memiliki antarmuka yang mendefinisikan, katakanlah, tipe data. Anda dapat memiliki enum untuk mengimplementasikan tipe sederhana, dan memiliki kelas normal untuk mengimplementasikan tipe rumit:
interfaceDataType{// methods here}enumSimpleDataTypeimplementsDataType{
INTEGER, STRING;// implement methods}classIdentifierDataTypeimplementsDataType{// implement interface and maybe add more specific methods}
Ya. Aneh !!. Enum sudah mengimplementasikan antarmuka Sebanding dan tidak mengizinkan untuk mengesampingkan. Saya mencari kode sumber java untuk kelas enum dan tidak dapat menemukan implementasi compareTo. Adakah yang bisa memberi tahu saya apa yang akan dibandingkan di dalam metode compareTo dan ENUM?
AKh
2
@Apakah itu membandingkan ordinals, berarti pemesanan alami adalah urutan konstanta enum dalam file sumber.
Jorn
Enum vars bersifat final dan jadi bandingkan terjadi dengan ==, bukan?
djangofan
@ Djangofan ya.
Jorn
17
Ada kasus yang sering saya gunakan. Saya memiliki IdUtilkelas dengan metode statis untuk bekerja dengan objek yang mengimplementasikan Identifiableantarmuka yang sangat sederhana :
publicinterfaceIdentifiable<K>{
K getId();}publicabstractclassIdUtil{publicstatic<T extendsEnum<T>&Identifiable<S>, S> T get(Class<T> type, S id){for(T t : type.getEnumConstants()){if(Util.equals(t.getId(), id)){return t;}}returnnull;}publicstatic<T extendsEnum<T>&Identifiable<S>, S extendsComparable<?super S>>List<T> getLower(T en){List<T> list =newArrayList<>();for(T t : en.getDeclaringClass().getEnumConstants()){if(t.getId().compareTo(en.getId())<0){
list.add(t);}}return list;}}
Karena Enums dapat mengimplementasikan antarmuka, mereka dapat digunakan untuk menegakkan secara ketat pola tunggal. Mencoba membuat kelas standar yang tunggal memungkinkan ...
untuk kemungkinan menggunakan teknik refleksi untuk mengekspos metode pribadi sebagai publik
untuk mewarisi dari singleton Anda dan mengganti metode singleton Anda dengan sesuatu yang lain
Enum sebagai lajang membantu mencegah masalah keamanan ini. Ini mungkin salah satu alasan yang berkontribusi untuk membiarkan Enums bertindak sebagai kelas dan mengimplementasikan antarmuka. Tebakan saja.
for inheriting from your singleton and overriding your singleton's methods with something else. Anda bisa menggunakan a final classuntuk mencegahnya
Dylanthepiguy
10
Diperlukan untuk ekstensibilitas - jika seseorang menggunakan API yang Anda kembangkan, enum yang Anda tetapkan bersifat statis; mereka tidak dapat ditambahkan atau dimodifikasi. Namun, jika Anda membiarkannya mengimplementasikan antarmuka, orang yang menggunakan API dapat mengembangkan enum mereka sendiri menggunakan antarmuka yang sama. Anda kemudian dapat mendaftarkan enum ini dengan manajer enum yang menggabungkan konglomerat dengan antarmuka standar.
Sunting: @Helper Method memiliki contoh sempurna untuk ini. Pikirkan tentang membuat perpustakaan lain mendefinisikan operator baru dan kemudian memberi tahu kelas manajer bahwa 'hei, enum ini ada - daftarkan itu'. Jika tidak, Anda hanya dapat mendefinisikan Operator dalam kode Anda sendiri - tidak akan ada perpanjangan.
Enum hanyalah kelas yang menyamar, jadi sebagian besar, apa pun yang dapat Anda lakukan dengan kelas yang dapat Anda lakukan dengan enum.
Saya tidak dapat memikirkan alasan mengapa enum tidak dapat mengimplementasikan antarmuka, pada saat yang sama saya juga tidak dapat memikirkan alasan yang baik bagi mereka untuk melakukannya.
Saya akan mengatakan begitu Anda mulai menambahkan hal-hal seperti antarmuka, atau metode untuk enum Anda harus benar-benar mempertimbangkan untuk menjadikannya kelas. Tentu saja saya yakin ada kasus yang valid untuk melakukan hal-hal non-tradisional enum, dan karena batasnya adalah buatan, saya mendukung membiarkan orang melakukan apa yang mereka inginkan di sana.
"... jadi untuk sebagian besar hal yang dapat kamu lakukan dengan sebuah kelas dapat kamu lakukan dengan sebuah enum", namun aku tidak bisa mengatakan memiliki enum ku mewarisi dari kelas abstrak. Jadi ya, penekanan pada "sebagian besar".
Adam Parkin
5
Itu karena enum semua memperpanjang java.lang.Enum, dan kelas Java hanya dapat diperluas dari satu kelas.
TofuBeer
6
Misalnya jika Anda memiliki enum Logger. Maka Anda harus memiliki metode logger seperti debug, info, peringatan dan kesalahan di antarmuka. Itu membuat kode Anda longgar digabungkan.
Penggunaan paling umum untuk ini adalah untuk menggabungkan nilai-nilai dari dua enum ke dalam satu kelompok dan memperlakukan mereka dengan cara yang sama. Misalnya, lihat cara bergabung dengan Buah dan Sayuran .
Salah satu kasus penggunaan terbaik bagi saya untuk menggunakan enum dengan antarmuka adalah filter Predicate. Ini adalah cara yang sangat elegan untuk memperbaiki kekurangan tipenya dari koleksi apache (Jika perpustakaan lain tidak dapat digunakan).
Posting di atas bahwa strategi yang disebutkan tidak cukup menekankan betapa penerapan pola strategi menggunakan enum yang ringan membuat Anda:
publicenumStrategy{
A {@Overridevoid execute(){System.out.print("Executing strategy A");}},
B {@Overridevoid execute(){System.out.print("Executing strategy B");}};abstractvoid execute();}
Anda dapat memiliki semua strategi di satu tempat tanpa memerlukan unit kompilasi terpisah untuk masing-masing. Anda mendapatkan pengiriman dinamis yang bagus hanya dengan:
Strategy.valueOf("A").execute();
Membuat java membaca hampir seperti bahasa yang diketik longgar yang bagus!
Enum seperti Kelas Java, mereka dapat memiliki Konstruktor, Metode, dll. Satu-satunya hal yang tidak dapat Anda lakukan dengannya adalah new EnumName(). Mesin virtual sudah ditentukan sebelumnya dalam deklarasi enum Anda.
Bagaimana dengan enum Foo extends SomeOtherClass? Jadi tidak sama dengan kelas reguler, pada kenyataannya, sangat berbeda.
Adam Parkin
@ Adam: Saya akan mengatakan bahwa cara yang mirip dengan Enums kelas jauh lebih banyak daripada cara di mana mereka berbeda dari kelas. Tapi, tidak, mereka tidak identik.
scottb
jika Anda mendekompilasi enum Anda akan melihat itu adalah kelas yang meluas Pencacahan dan memiliki "konstanta" yang sudah dipakai di bidang konstruktor / inisialisasi.
Cosmin Cosmin
3
Kemungkinan lain:
publicenumConditionsToBeSatisfiedimplementsPredicate<Number>{
IS_NOT_NULL(Objects::nonNull,"Item is null"),
IS_NOT_AN_INTEGER(item -> item instanceofInteger,"Item is not an integer"),
IS_POSITIVE(item -> item instanceofInteger&&(Integer) item >0,"Item is negative");privatefinalPredicate<Number> predicate;privatefinalString notSatisfiedLogMessage;ConditionsToBeSatisfied(finalPredicate<Number> predicate,finalString notSatisfiedLogMessage){this.predicate = predicate;this.notSatisfiedLogMessage = notSatisfiedLogMessage;}@Overridepublicboolean test(finalNumber item){finalboolean isNotValid = predicate.negate().test(item);if(isNotValid){
log.warn("Invalid {}. Cause: {}", item, notSatisfiedLogMessage);}return predicate.test(item);}}
dan menggunakan:
Predicate<Number> p = IS_NOT_NULL.and(IS_NOT_AN_INTEGER).and(IS_POSITIVE);
Saat membuat konstanta dalam file jar, sering kali bermanfaat untuk membiarkan pengguna memperluas nilai enum. Kami menggunakan enum untuk kunci PropertyFile dan macet karena tidak ada yang bisa menambahkan yang baru! Di bawah ini akan bekerja lebih baik.
Saya telah mengisi JavaFX ComboBox dengan nilai-nilai Enum. Saya memiliki antarmuka, Dapat Diidentifikasi (menetapkan satu metode: mengidentifikasi), yang memungkinkan saya untuk menentukan bagaimana objek mengidentifikasi dirinya ke aplikasi saya untuk tujuan pencarian. Antarmuka ini memungkinkan saya untuk memindai daftar semua jenis objek (bidang mana pun yang digunakan objek untuk identitas) untuk pencocokan identitas.
Saya ingin menemukan kecocokan untuk nilai identitas di daftar ComboBox saya. Untuk menggunakan kemampuan ini pada ComboBox saya yang berisi nilai-nilai Enum, saya harus dapat mengimplementasikan antarmuka yang dapat diidentifikasi dalam Enum saya (yang, jika terjadi, sepele untuk diimplementasikan dalam kasus Enum).
Saya menggunakan enum dalam antarmuka yang menggambarkan strategi untuk menjaga kontrol instance (masing-masing strategi adalah Singleton) dari sana.
publicinterfaceVectorizeStrategy{/**
* Keep instance control from here.
*
* Concrete classes constructors should be package private.
*/enumConcreteStrategyimplementsVectorizeStrategy{
DEFAULT (newVectorizeImpl());privatefinalVectorizeStrategy INSTANCE;ConcreteStrategy(VectorizeStrategy concreteStrategy){
INSTANCE = concreteStrategy;}@OverridepublicVectorImageGridIntersections processImage(MarvinImage img){return INSTANCE.processImage(img);}}/**
* Should perform edge Detection in order to have lines, that can be vectorized.
*
* @param img An Image suitable for edge detection.
*
* @return the VectorImageGridIntersections representing img's vectors
* intersections with the grids.
*/VectorImageGridIntersections processImage(MarvinImage img);}
Fakta bahwa enum mengimplementasikan strategi adalah mudah untuk memungkinkan kelas enum untuk bertindak sebagai proksi untuk Instance terlampir. yang juga mengimplementasikan antarmuka.
itu adalah semacam strategyEnumProxy: P kode clent terlihat seperti ini:
Jawaban:
Enum tidak hanya harus mewakili set pasif (misalnya warna). Mereka dapat mewakili objek yang lebih kompleks dengan fungsionalitas, dan karenanya Anda mungkin ingin menambahkan fungsionalitas lebih lanjut untuk ini - misalnya Anda mungkin memiliki antarmuka seperti
Printable
,Reportable
dll. Dan komponen yang mendukung ini.sumber
Berikut adalah satu contoh (yang serupa / lebih baik ditemukan di Java Edisi 2 Efektif):
Sekarang untuk mendapatkan daftar Operator Sederhana + Kompleks:
Jadi di sini Anda menggunakan antarmuka untuk mensimulasikan enum yang dapat diperluas (yang tidak mungkin dilakukan tanpa menggunakan antarmuka).
sumber
The
Comparable
contoh yang diberikan oleh beberapa orang di sini yang salah, karenaEnum
sudah mengimplementasikan itu. Anda bahkan tidak bisa menimpanya.Contoh yang lebih baik adalah memiliki antarmuka yang mendefinisikan, katakanlah, tipe data. Anda dapat memiliki enum untuk mengimplementasikan tipe sederhana, dan memiliki kelas normal untuk mengimplementasikan tipe rumit:
sumber
Ada kasus yang sering saya gunakan. Saya memiliki
IdUtil
kelas dengan metode statis untuk bekerja dengan objek yang mengimplementasikanIdentifiable
antarmuka yang sangat sederhana :Jika saya membuat
Identifiable
enum
:Maka saya bisa mendapatkannya dengan
id
cara ini:sumber
Karena Enums dapat mengimplementasikan antarmuka, mereka dapat digunakan untuk menegakkan secara ketat pola tunggal. Mencoba membuat kelas standar yang tunggal memungkinkan ...
Enum sebagai lajang membantu mencegah masalah keamanan ini. Ini mungkin salah satu alasan yang berkontribusi untuk membiarkan Enums bertindak sebagai kelas dan mengimplementasikan antarmuka. Tebakan saja.
Lihat /programming/427902/java-enum-singleton dan kelas Singleton di java untuk diskusi lebih lanjut.
sumber
for inheriting from your singleton and overriding your singleton's methods with something else
. Anda bisa menggunakan afinal class
untuk mencegahnyaDiperlukan untuk ekstensibilitas - jika seseorang menggunakan API yang Anda kembangkan, enum yang Anda tetapkan bersifat statis; mereka tidak dapat ditambahkan atau dimodifikasi. Namun, jika Anda membiarkannya mengimplementasikan antarmuka, orang yang menggunakan API dapat mengembangkan enum mereka sendiri menggunakan antarmuka yang sama. Anda kemudian dapat mendaftarkan enum ini dengan manajer enum yang menggabungkan konglomerat dengan antarmuka standar.
Sunting: @Helper Method memiliki contoh sempurna untuk ini. Pikirkan tentang membuat perpustakaan lain mendefinisikan operator baru dan kemudian memberi tahu kelas manajer bahwa 'hei, enum ini ada - daftarkan itu'. Jika tidak, Anda hanya dapat mendefinisikan Operator dalam kode Anda sendiri - tidak akan ada perpanjangan.
sumber
Enum hanyalah kelas yang menyamar, jadi sebagian besar, apa pun yang dapat Anda lakukan dengan kelas yang dapat Anda lakukan dengan enum.
Saya tidak dapat memikirkan alasan mengapa enum tidak dapat mengimplementasikan antarmuka, pada saat yang sama saya juga tidak dapat memikirkan alasan yang baik bagi mereka untuk melakukannya.
Saya akan mengatakan begitu Anda mulai menambahkan hal-hal seperti antarmuka, atau metode untuk enum Anda harus benar-benar mempertimbangkan untuk menjadikannya kelas. Tentu saja saya yakin ada kasus yang valid untuk melakukan hal-hal non-tradisional enum, dan karena batasnya adalah buatan, saya mendukung membiarkan orang melakukan apa yang mereka inginkan di sana.
sumber
Misalnya jika Anda memiliki enum Logger. Maka Anda harus memiliki metode logger seperti debug, info, peringatan dan kesalahan di antarmuka. Itu membuat kode Anda longgar digabungkan.
sumber
Penggunaan paling umum untuk ini adalah untuk menggabungkan nilai-nilai dari dua enum ke dalam satu kelompok dan memperlakukan mereka dengan cara yang sama. Misalnya, lihat cara bergabung dengan Buah dan Sayuran .
sumber
Salah satu kasus penggunaan terbaik bagi saya untuk menggunakan enum dengan antarmuka adalah filter Predicate. Ini adalah cara yang sangat elegan untuk memperbaiki kekurangan tipenya dari koleksi apache (Jika perpustakaan lain tidak dapat digunakan).
sumber
Posting di atas bahwa strategi yang disebutkan tidak cukup menekankan betapa penerapan pola strategi menggunakan enum yang ringan membuat Anda:
Anda dapat memiliki semua strategi di satu tempat tanpa memerlukan unit kompilasi terpisah untuk masing-masing. Anda mendapatkan pengiriman dinamis yang bagus hanya dengan:
Membuat java membaca hampir seperti bahasa yang diketik longgar yang bagus!
sumber
Enum seperti Kelas Java, mereka dapat memiliki Konstruktor, Metode, dll. Satu-satunya hal yang tidak dapat Anda lakukan dengannya adalah
new EnumName()
. Mesin virtual sudah ditentukan sebelumnya dalam deklarasi enum Anda.sumber
enum Foo extends SomeOtherClass
? Jadi tidak sama dengan kelas reguler, pada kenyataannya, sangat berbeda.Kemungkinan lain:
dan menggunakan:
sumber
Saat membuat konstanta dalam file jar, sering kali bermanfaat untuk membiarkan pengguna memperluas nilai enum. Kami menggunakan enum untuk kunci PropertyFile dan macet karena tidak ada yang bisa menambahkan yang baru! Di bawah ini akan bekerja lebih baik.
Diberikan:
dan:
seseorang dapat memiliki satu enum di dalam toples:
dan pengguna dapat memperluasnya untuk menambahkan warnanya sendiri:
sumber
Inilah alasan saya mengapa ...
Saya telah mengisi JavaFX ComboBox dengan nilai-nilai Enum. Saya memiliki antarmuka, Dapat Diidentifikasi (menetapkan satu metode: mengidentifikasi), yang memungkinkan saya untuk menentukan bagaimana objek mengidentifikasi dirinya ke aplikasi saya untuk tujuan pencarian. Antarmuka ini memungkinkan saya untuk memindai daftar semua jenis objek (bidang mana pun yang digunakan objek untuk identitas) untuk pencocokan identitas.
Saya ingin menemukan kecocokan untuk nilai identitas di daftar ComboBox saya. Untuk menggunakan kemampuan ini pada ComboBox saya yang berisi nilai-nilai Enum, saya harus dapat mengimplementasikan antarmuka yang dapat diidentifikasi dalam Enum saya (yang, jika terjadi, sepele untuk diimplementasikan dalam kasus Enum).
sumber
Saya menggunakan enum dalam antarmuka yang menggambarkan strategi untuk menjaga kontrol instance (masing-masing strategi adalah Singleton) dari sana.
Fakta bahwa enum mengimplementasikan strategi adalah mudah untuk memungkinkan kelas enum untuk bertindak sebagai proksi untuk Instance terlampir. yang juga mengimplementasikan antarmuka.
itu adalah semacam strategyEnumProxy: P kode clent terlihat seperti ini:
Jika itu tidak mengimplementasikan antarmuka itu sudah:
sumber