JavaRush /בלוג Java /Random-HE /Enum ב-Java. דוגמאות מעשיות. הוספת בנאים ושיטות

Enum ב-Java. דוגמאות מעשיות. הוספת בנאים ושיטות

פורסם בקבוצה
שלום! היום נדבר על סוג נתונים מיוחד בג'אווה - Enum(קיצור של ספירה). מה התכונה שלהם? בואו נדמיין שאנחנו צריכים ליישם חודשים בתוכנית. Enum.  דוגמאות מעשיות.  הוספת בנאים ושיטות - 1נראה, מה הבעיה? אתה רק צריך לקבוע אילו נכסים יש בכל חודש. אולי צריך קודם כל את שם החודש ומספר הימים בו. הפתרון לבעיה נראה די פשוט:
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 +
               '}';
   }
}
סט מלא בבקשה! יש לנו כיתה Month, השדות הדרושים, מגדירים-מגדיר, toString(). אלא אם כן equals()אתה hashCode()צריך להוסיף את זה בשביל אושר מוחלט :) עם זאת, יש לנו בעיה מושגית. כפי שאתם אולי זוכרים, אחד היתרונות העיקריים של OOP הוא בכך שהוא מקל על מודלים של ישויות בעולם האמיתי. כיסא, מכונית, כוכב לכת - קל לייצג את כל המושגים הללו מחיי היומיום בתוכנית באמצעות הפשטה. הבעיה היא שלישויות מסוימות בעולם האמיתי יש מגוון משמעויות מוגבל בהחלט. יש רק 4 עונות בשנה. יש רק 7 תווים במוזיקה. יש רק 12 חודשים בלוח השנה. לאוקיינוס ​​יש רק 11 חברים (למרות שזה נתון לוויכוח :)) במילים אחרות, מחלקה רגילה של Java לא מסוגלת לדגמן את הישויות הללו ולכבד את האילוצים הטבעיים שלהן. בכיתה שלנו Monthיש את כל התחומים הדרושים. אבל אם מתכנת אחר ישתמש בזה, אף אחד לא ימנע ממנו ליצור אובייקטים מטורפים לחלוטין:
public class Main {

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

}
אם זה יופיע בתוכנית, לא יהיה קל למצוא את האשם! מצד אחד, המתכנת שיצר את האובייקטים יכול היה להבין שהשיעור Monthמתכוון ל"חודש בשנה" ולא לכתוב שטויות כאלה. מצד שני, הוא רק ניצל את ההזדמנויות שמעצב הכיתה סיפק לו. האם אני יכול להקצות שמות ומספר ימים? הוא מינה אותו. מה לעשות במצב כזה? לפני שחרורו של שפת Java גרסה 1.5, מתכנתים היו צריכים, בכנות, לצאת מזה :) באותם ימים, הם יצרו את המבנים הבאים:
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 +
               '}';
   }
}
כאן פישטנו את מספר החודשים לשלושה במקום שנים עשר כדי שהדוגמה תהיה קצרה יותר. עיצובים כאלה אפשרו לפתור את הבעיה. האפשרויות לאובייקטים שנוצרו הוגבלו על ידי בנאי פרטי:
private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }
מתכנתים המשתמשים במחלקה לא יכלו ליצור פשוט Month. הם נאלצו להשתמש באובייקטים סטטיים אחרונים שסופקו על ידי מפתח הכיתה. זה נראה בערך כך:
public class Main {

   public static void main(String[] args) {

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

}
עם זאת, מפתחי Java הבחינו בבעיה קיימת. כמובן, זה נהדר שמתכנתים הצליחו להמציא פתרון באמצעות הכלים הזמינים בשפה, אבל זה לא נראה כל כך פשוט! היה צורך בפתרון ברור, נגיש אפילו למתחילים. כך הופיע ב-Java Enum. בעיקרו של דבר, Enumזוהי מחלקת Java המספקת קבוצה מוגבלת של אובייקטי ערך. כך זה נראה:
public enum Month {

   JANUARY,
   FEBRUARY,
   MARCH
}
בהגדרה ציינו שמדובר Enumבמחלקת Java, אבל האם זה באמת כך? כן, ואנחנו אפילו יכולים לבדוק את זה. נסה, למשל, לרשת את שלנו enum Monthמכיתה אחרת:
public abstract class AbstractMonth {
}

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

   JANUARY,
   FEBRUARY,
   MARCH
}
למה זה קורה? כשאנחנו כותבים לתוכנית:
public enum Month
המהדר ממיר את הפקודה הזו לקוד כך:
public Class Month extends Enum
כפי שאתה כבר יודע, ירושה מרובה אינה מותרת ב-Java. לכן, AbstractMonthלא יכולנו לרשת מ. Enumכיצד ניתן להשתמש בעיצוב החדש הזה ? ובמה זה שונה מהעיצוב הישן עם static finalשדות? ובכן, למשל, העיצוב הישן לא איפשר לנו להשתמש במערכת הערכים שלנו בביטויים switch. תארו לעצמכם שאנחנו רוצים ליצור תוכנית שתזכיר לנו אילו חגים נחוגים החודש:
public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {

           //error!
           case JANUARY:
       }
   }
}
כאן, כפי שאתה יכול לראות, המהדר זורק שגיאה. אבל אחרי ש-Java 1.5 הופיע enum, הכל נעשה הרבה יותר פשוט:
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);

   }

}
פלט מסוף:

7 января будет Рождество!
שימו לב: הגישה לאובייקטים Enumנשארת סטטית, כפי שהייתה לפני Java 1.5. אנחנו לא צריכים ליצור אובייקט Monthכדי לגשת לחודשים. כשעובדים עם ספירות, חשוב מאוד לא לשכוח שמדובר Enumבכיתה מן המניין. המשמעות היא שבמידת הצורך ניתן להגדיר בו בנאים ושיטות. לדוגמה, בקטע הקוד הקודם פשוט ציינו את הערכים JANUARY, FEBRUARY, MARCH. עם זאת, אנו יכולים להרחיב את שלנו enum Monthכך:
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 +
               '}';
   }
}
כאן הוספנו לשלנו 2 שדות enum- שם החודש ומספר הימים, בנאי המשתמש בשדות אלו, מגדירים-מגדי, מתודה toString()וכן 2 שיטות סטטיות. כפי שאתה יכול לראות, לא היו בעיות עם זה: כפי שאמרנו קודם, enumזהו שיעור מן המניין:
import java.util.Arrays;

public class Main {

   public static void main(String[] args) {

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

   }

}
פלט מסוף:

[Month{name='Июнь', daysCount=30}, Month{name='Июль', daysCount=31}, Month{name='Август', daysCount=31}]
לבסוף, אני רוצה להמליץ ​​לך על ספר שימושי ביותר על ג'אווה, כלומר "ג'אווה יעילה" מאת ג'ושוע בלוך . Enum.  דוגמאות מעשיות.  הוספת בנאים ושיטות - 3המחבר הוא אחד היוצרים של ג'אווה, כך שאתה בהחלט יכול לסמוך על עצתו לגבי שימוש נכון ומוכשר בכלי שפה :) ביחס להרצאה שלנו, אני ממליץ לך להקדיש תשומת לב מיוחדת לפרק של הספר המוקדש ל enum. שתהיה לך קריאה פורייה! :)
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION