JavaRush /Blog Java /Random-VI /Enum trong Java. Ví dụ thực tế. Thêm hàm tạo và phương th...

Enum trong Java. Ví dụ thực tế. Thêm hàm tạo và phương thức

Xuất bản trong nhóm
Xin chào! Hôm nay chúng ta sẽ nói về một kiểu dữ liệu đặc biệt trong Java - Enum(viết tắt của enumeration). Tính năng của họ là gì? Hãy tưởng tượng rằng chúng ta cần triển khai các tháng trong chương trình. liệt kê.  Ví dụ thực tế.  Thêm hàm tạo và phương thức - 1Có vẻ như, vấn đề là gì? Bạn chỉ cần xác định tháng nào có những thuộc tính nào. Có lẽ trước hết chúng ta cần tên của tháng và số ngày trong đó. Giải pháp cho vấn đề trông khá đơn giản:
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 +
               '}';
   }
}
Xin vui lòng đặt trọn bộ! Chúng ta có một lớp Month, các trường cần thiết, getters-setters, toString(). Trừ khi equals()bạn hashCode()cần thêm nó để có được hạnh phúc trọn vẹn :) Tuy nhiên, chúng tôi có một vấn đề về khái niệm. Như bạn có thể nhớ, một trong những ưu điểm chính của OOP là nó giúp dễ dàng lập mô hình các thực thể trong thế giới thực. Một chiếc ghế, một chiếc ô tô, một hành tinh - tất cả những khái niệm từ cuộc sống hàng ngày này đều dễ dàng được thể hiện trong một chương trình bằng cách sử dụng tính trừu tượng. Vấn đề là một số thực thể trong thế giới thực có phạm vi ý nghĩa rất hạn chế. Một năm chỉ có 4 mùa. Trong âm nhạc chỉ có 7 nốt. Trong lịch chỉ có 12 tháng. Ocean chỉ có 11 người bạn (mặc dù điều này còn gây tranh cãi :)) Nói cách khác, một lớp Java thông thường không thể mô hình hóa các thực thể này và tôn trọng các ràng buộc tự nhiên của chúng. Lớp của chúng tôi Monthcó tất cả các trường cần thiết. Nhưng nếu một lập trình viên khác sử dụng nó, sẽ không ai ngăn cản anh ta tạo ra những đồ vật hoàn toàn điên rồ:
public class Main {

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

}
Nếu điều này xuất hiện trong chương trình, sẽ không dễ để tìm ra thủ phạm! Một mặt, lập trình viên tạo ra các đối tượng có thể hiểu rằng lớp này Monthcó nghĩa là “tháng trong năm” và không viết những điều vô nghĩa như vậy. Mặt khác, anh ta chỉ đang tận dụng những cơ hội mà người thiết kế lớp học mang lại cho anh ta. Tôi có thể chỉ định bất kỳ tên và số ngày nào không? Ông đã bổ nhiệm nó. Phải làm gì trong tình huống như vậy? Trước khi phát hành ngôn ngữ Java phiên bản 1.5, thành thật mà nói, các lập trình viên đã phải thoát khỏi nó :) Vào những ngày đó, họ đã tạo ra các cấu trúc sau:
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("Январь", 31);
   public static Month FEBRUARY = new Month("Февраль", 28);
   public static Month MARCH = new Month("Март", 31);

   @Override
   public String toString() {
       return "Month{" +
               "name='" + name + '\'' +
               ", daysCount=" + daysCount +
               '}';
   }
}
Ở đây chúng tôi đã đơn giản hóa số tháng thành ba thay vì mười hai để ví dụ ngắn hơn. Những thiết kế như vậy đã giúp giải quyết được vấn đề. Các tùy chọn cho các đối tượng được tạo bị giới hạn bởi một hàm tạo riêng:
private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }
Các lập trình viên sử dụng lớp này không thể đơn giản tạo các tệp Month. Họ buộc phải sử dụng những đối tượng tĩnh cuối cùng do nhà phát triển lớp cung cấp. Nó trông giống như thế này:
public class Main {

   public static void main(String[] args) {

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

}
Tuy nhiên, các nhà phát triển Java đã nhận thấy một vấn đề hiện có. Tất nhiên, thật tuyệt khi các lập trình viên có thể đưa ra giải pháp bằng cách sử dụng các công cụ có sẵn trong ngôn ngữ, nhưng nó trông không đơn giản như vậy! Cần có một giải pháp rõ ràng, dễ tiếp cận ngay cả với người mới bắt đầu. Đây là cách .. xuất hiện trong Java Enum. Về cơ bản, Enumnó là một lớp Java cung cấp một tập hợp giới hạn các đối tượng giá trị. Đây là những gì nó trông giống như:
public enum Month {

   JANUARY,
   FEBRUARY,
   MARCH
}
Trong định nghĩa, chúng tôi đã chỉ ra rằng Enumđây là một lớp Java, nhưng điều này có thực sự đúng không? Có, và chúng tôi thậm chí có thể kiểm tra nó. Ví dụ: hãy thử kế thừa lớp của chúng tôi enum Monthtừ một số lớp khác:
public abstract class AbstractMonth {
}

//ошибка! No extends clause allowed to enum
public enum Month extends AbstractMonth {

   JANUARY,
   FEBRUARY,
   MARCH
}
Tại sao chuyện này đang xảy ra? Khi chúng ta viết vào một chương trình:
public enum Month
Trình biên dịch chuyển lệnh này thành mã như thế này:
public Class Month extends Enum
Như bạn đã biết, đa kế thừa không được phép trong Java. Vì vậy, AbstractMonthchúng tôi không thể kế thừa từ. Thiết kế mới này có thể Enumđược sử dụng như thế nào? Và nó có gì khác biệt so với thiết kế cũ với static finalcác cánh đồng? Ví dụ: thiết kế cũ không cho phép chúng tôi sử dụng tập hợp giá trị của riêng mình trong switchbiểu thức -. Hãy tưởng tượng rằng chúng ta muốn tạo một chương trình nhắc nhở chúng ta về những ngày lễ nào được tổ chức trong tháng này:
public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {

           //error!
           case JANUARY:
       }
   }
}
Ở đây, như bạn có thể thấy, trình biên dịch đưa ra một lỗi. Nhưng sau khi Java 1.5 xuất hiện enum, mọi chuyện trở nên đơn giản hơn rất nhiều:
public enum Month {

   JANUARY,
   FEBRUARY,
   MARCH
}

public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {

           case JANUARY:
               System.out.println("7 января будет Рождество!");
               break;
           case FEBRUARY:
               System.out.println("В феврале празднуется День Защитника Отечества - 23 февраля!");
               break;
           case MARCH:
               System.out.println("В марте отмечается Всемирный Женский День - 8 марта!");
               break;
       }
   }
}



public class Main {

   public static void main(String[] args) {

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

   }

}
Đầu ra của bảng điều khiển:

7 января будет Рождество!
Xin lưu ý: quyền truy cập vào các đối tượng Enumvẫn ở trạng thái tĩnh, giống như trước Java 1.5. Chúng ta không cần tạo một đối tượng Monthđể truy cập tháng. Khi làm việc với các bảng liệt kê, điều rất quan trọng là đừng quên rằng Enumđây là một lớp chính thức. Điều này có nghĩa là, nếu cần, bạn có thể định nghĩa các hàm tạo và phương thức trong đó. Ví dụ: trong đoạn mã trước, chúng ta chỉ xác định các giá trị THÁNG 1, THÁNG 2, THÁNG 3. Tuy nhiên, chúng ta có thể mở rộng phạm vi của mình enum Monthnhư thế này:
public enum Month {

   JANUARY("Январь", 31),
   FEBRUARY("Февраль", 28),
   MARCH("Март", 31),
   APRIL("Апрель", 30),
   MAY("Май", 31),
   JUNE("Июнь", 30),
   JULY("Июль", 31),
   AUGUST("Август", 31),
   SEPTEMBER("Сентябрь", 30),
   OCTOBER("Октябрь", 31),
   NOVEMBER("Ноябрь", 30),
   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 +
               '}';
   }
}
Ở đây, chúng tôi đã thêm 2 trường vào trường của mình enum- tên của tháng và số ngày, một hàm tạo sử dụng các trường này, getters-setters, một phương thức toString()cũng như 2 phương thức tĩnh. Như bạn có thể thấy, không có vấn đề gì với điều này: như chúng tôi đã nói trước đó, enumđây là một lớp chính thức:
import java.util.Arrays;

public class Main {

   public static void main(String[] args) {

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

   }

}
Đầu ra của bảng điều khiển:

[Month{name='Июнь', daysCount=30}, Month{name='Июль', daysCount=31}, Month{name='Август', daysCount=31}]
Cuối cùng, tôi muốn giới thiệu cho bạn một cuốn sách cực kỳ hữu ích về Java, đó là “Java hiệu quả” của Joshua Bloch . liệt kê.  Ví dụ thực tế.  Thêm hàm tạo và phương thức - 3Tác giả là một trong những người tạo ra Java, vì vậy bạn chắc chắn có thể tin tưởng vào lời khuyên của anh ấy về cách sử dụng đúng và thành thạo các công cụ ngôn ngữ :) Liên quan đến bài giảng của chúng tôi, tôi khuyên bạn nên đặc biệt chú ý đến chương của cuốn sách dành riêng cho enum. Chúc bạn đọc hiệu quả! :)
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION