CodeGym /Blog Java /rawak /Enum. Contoh praktikal. Menambah pembina dan kaedah
John Squirrels
Tahap
San Francisco

Enum. Contoh praktikal. Menambah pembina dan kaedah

Diterbitkan dalam kumpulan
Hai! Hari ini kita akan bercakap tentang salah satu jenis data khas Java: Enum(singkatan untuk "penghitungan"). Apa yang menjadikannya istimewa? Cuba kita bayangkan apa yang kita perlukan untuk melaksanakan "bulan" dalam sesuatu program. Enum.  Contoh praktikal.  Menambah pembina dan kaedah - 1 Nampak tak bermasalah kan? Kita hanya perlu tentukan hartanah yang ada pada mana-mana bulan. Mungkin kita perlu nama bulan dan bilangan hari di dalamnya. Penyelesaiannya kelihatan agak mudah:

public class Month {

   private String name;
   private int daysCount;

   public Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public int getDaysCount() {
       return daysCount;
   }

   public void setDaysCount(int daysCount) {
       this.daysCount = daysCount;
   }

   @Override
   public String toString() {
       return "Month{" +
               "name='" + name + '\'' +
               ", daysCount=" + daysCount +
               '}';
   }
}
Seluruh shabang! Kami mempunyai Monthkelas, medan yang diperlukan, pengambil/penetap, dan toString(). Melainkan, sudah tentu, kita perlu menambah equals()danhashCode()untuk mencapai kebahagiaan yang lengkap :) Tetapi di sini kita mempunyai masalah konsep. Seperti yang anda mungkin ingat, salah satu kelebihan utama OOP ialah ia memudahkan untuk memodelkan entiti dari dunia sebenar. Kerusi, kereta, planet — semua konsep dari kehidupan biasa ini mudah diwakili dalam program dengan bantuan abstraksi. Masalahnya ialah sesetengah entiti dunia nyata mempunyai julat nilai yang sangat terhad. Hanya ada 4 musim dalam setahun. Terdapat hanya 8 not dalam satu oktaf. Kalendar hanya mempunyai 12 bulan. Dan Danny Ocean of Ocean's 11 hanya mempunyai 11 rakan (walaupun ini tidak penting :)) Apa yang penting ialah kelas Java biasa tidak dapat memodelkan entiti ini dan menguatkuasakan batasan semula jadi mereka. kamiMonthkelas mempunyai semua medan yang diperlukan. Tetapi jika pengaturcara lain menggunakannya, tiada siapa boleh menghalangnya daripada mencipta objek yang benar-benar gila:

public class Main {

   Month month1 = new Month("lolkek", 322);
   Month month2 = new Month("yahoooooooooooo", 12345);

}
Jika ini muncul dalam kod kami, bukan mudah untuk mencari pelakunya! Di satu pihak, pengaturcara yang mencipta objek mungkin menyedari bahawa Monthkelas itu bermaksud "bulan dalam setahun" dan tidak menulis omong kosong seperti itu. Sebaliknya, pengaturcara hanya memanfaatkan kebolehan yang diberikan oleh pereka kelas. Adakah mungkin untuk menetapkan nama dan bilangan hari sewenang-wenangnya? Itulah yang kami dapat. Apa yang perlu kita lakukan dalam keadaan ini? Sejujurnya, sebelum Java 1.5 dikeluarkan, pengaturcara perlu menjadi kreatif :) Pada masa itu, mereka mencipta struktur seperti ini:

public class Month {

   private String name;
   private int daysCount;

   private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }

   public static Month JANUARY = new Month("January", 31);
   public static Month FEBRUARY = new Month("February", 28);
   public static Month MARCH = new Month("March", 31);

   @Override
   public String toString() {
       return "Month{" +
               "name='" + name + '\'' +
               ", daysCount=" + daysCount +
               '}';
   }
}
Di sini kita telah mengurangkan bilangan bulan daripada dua belas kepada tiga untuk menjadikan contoh lebih pendek. Reka bentuk sedemikian memungkinkan untuk menyelesaikan masalah. Keupayaan untuk mencipta objek terhad kepada pembina peribadi:

private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }
Pengaturcara yang menggunakan kelas tidak boleh mencipta Monthobjek sahaja. Mereka terpaksa menggunakan objek statik akhir yang disediakan oleh pembangun kelas. Sebagai contoh, seperti ini:

public class Main {

   public static void main(String[] args) {

       Month january = Month.JANUARY;
       System.out.println(january);
   }

}
Tetapi, pembangun Java menarik perhatian kepada masalah yang sedia ada. Sudah tentu, sangat bagus bahawa pengaturcara dapat menghasilkan penyelesaian menggunakan alat yang tersedia dalam bahasa, tetapi ia tidak kelihatan sangat mudah! Penyelesaian yang jelas diperlukan, walaupun untuk orang baru. Dan begitulah Enummuncul di Jawa. Pada asasnya, Enumialah kelas Java yang menyediakan set nilai objek terhad. Begini rupanya:

public enum Month {
  
   JANUARY,
   FEBRUARY,
   MARCH
}
Dalam takrifan, kami menunjukkan bahawa itu Enumadalah kelas Java, tetapi adakah itu benar? Ya, dan kami juga boleh mengesahkannya. Sebagai contoh, cuba jadikan Monthenum kami mewarisi beberapa kelas lain:

public abstract class AbstractMonth {
}

// Error! The extends clause cannot be used with an enum
public enum Month extends AbstractMonth {

   JANUARY,
   FEBRUARY,
   MARCH
}
Mengapa ia berlaku? Apabila kita menulis:

public enum Month
pengkompil menukar pernyataan ini kepada kod berikut:

public Class Month extends Enum
Seperti yang anda sedia maklum, Java tidak menyokong pelbagai warisan. Oleh itu, kita tidak boleh mewarisi AbstractMonth. Bagaimanakah binaan baru ini, Enum, boleh digunakan? Dan bagaimana ia berbeza daripada binaan lama dengan static finalmedan? Nah, sebagai contoh, binaan lama tidak membenarkan kami menggunakan set nilai kami sendiri dalam switchpernyataan. Bayangkan kita ingin mencipta satu program yang akan mengingatkan kita tentang cuti yang disambut setiap bulan:

public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {

           // Error!
           case JANUARY:
       }
   }
}
Seperti yang anda lihat, pengkompil membuang ralat di sini. Tetapi setelah enummuncul di Java 1.5, semuanya menjadi lebih mudah:

public enum Month {

   JANUARY,
   FEBRUARY,
   MARCH
}

public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {
          
           case JANUARY:
               System.out.println("New Year's Day is January 1st!");
               break;
           case FEBRUARY:
               System.out.println("Valentine's Day is February 14th!");
               break;
           case MARCH:
               System.out.println("Saint Patrick's Day is March 17th!");
               break;
       }
   }
}


public class Main {

   public static void main(String[] args) {

       HolidayReminder reminder = new HolidayReminder();
       reminder.printHolidays(Month.JANUARY);

   }

}
Output konsol:

New Year's Day is January 1st!
Ambil perhatian bahawa akses kepada Enumobjek kekal statik, sama seperti sebelum Java 1.5. Kami tidak perlu mencipta Monthobjek untuk mengakses bulan. Apabila bekerja dengan enums, adalah sangat penting untuk tidak lupa bahawa ia Enumadalah kelas yang lengkap. Ini bermakna, jika perlu, anda boleh menentukan pembina dan kaedah di dalamnya. Sebagai contoh, dalam serpihan kod sebelumnya, kami hanya menentukan nilai: JANUARI, FEBRUARI, MAC. Walau bagaimanapun, kami boleh mengembangkan Monthenum kami seperti ini:

public enum Month {

   JANUARY("January", 31),
   FEBRUARY("February", 28),
   MARCH("March", 31),
   APRIL("April", 30),
   MAY("May", 31),
   JUNE("June", 30),
   JULY("July", 31),
   AUGUST("August", 31),
   SEPTEMBER("September", 30),
   OCTOBER("October", 31),
   NOVEMBER("November", 30),
   DECEMBER("December", 31);

   private String name;
   private int daysCount;

   Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }

   public static Month[] getWinterMonths() {

       return new Month[]{DECEMBER, JANUARY, FEBRUARY};
   }

   public static Month[] getSummerMonths() {

       return new Month[]{JUNE, JULY, AUGUST};
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public int getDaysCount() {
       return daysCount;
   }

   public void setDaysCount(int daysCount) {
       this.daysCount = daysCount;
   }

   @Override
   public String toString() {
       return "Month{" +
               "name='" + name + '\'' +
               ", daysCount=" + daysCount +
               '}';
   }
}
Di sini kami memberikan enum2 medan kami (nama bulan dan bilangan hari), pembina yang menggunakan medan ini, pengambil/penetap, kaedah toString()dan 2 kaedah statik. Seperti yang anda lihat, tidak ada masalah dengan ini. Sekali lagi, Enumbenar-benar kelas yang lengkap:

import java.util.Arrays;

public class Main {

   public static void main(String[] args) {

       System.out.println(Arrays.toString(Month.getSummerMonths()));

   }

}
Output konsol:

[Month{name='June', daysCount=30}, Month{name='July', daysCount=31}, Month{name='August', daysCount=31}]
Akhir sekali, saya ingin mengesyorkan buku Java yang sangat berguna, iaitu "Java Berkesan" oleh Joshua Bloch . Enum.  Contoh praktikal.  Menambah pembina dan kaedah - 3Pengarang ialah salah seorang pencipta Java, jadi anda pasti boleh mempercayai nasihatnya tentang cara menggunakan alat bahasa dengan betul dan cekap :) Berkenaan dengan pelajaran kami, saya mengesyorkan agar anda memberi perhatian khusus kepada bab buku tentang Enum. Selamat membaca! :)
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION