בעת התכנות, אנו נתקלים לעתים קרובות בצורך להגביל את סט הערכים התקפים עבור סוג נתונים מסוים. אז, למשל, ליום בשבוע יכולים להיות 7 ערכים שונים, לחודש בשנה יכולים להיות 12, ולעונה יכולה להיות 4. כדי לפתור בעיות כאלה, שפות תכנות רבות עם הקלדה סטטית מספקות סוג נתונים מיוחד - ספירה ( איברי Enum הם מופעים
אלמנטים
enum
). ספירה לא הופיעה ב-Java מיד. מבנה שפה מיוחד enum
הוצג החל מגרסה 1.5. עד לנקודה זו, מתכנתים השתמשו בשיטות אחרות כדי ליישם ספירות.
בניית אנדום
נתחיל עם דוגמה. נתארenum
את סוג הנתונים לאחסון העונה באמצעות:
enum Season { WINTER, SPRING, SUMMER, AUTUMN }
ובכן, דוגמה פשוטה לשימוש בו:
Season season = Season.SPRING;
if (season == Season.SPRING) season = Season.SUMMER;
System.out.println(season);
כתוצאה מכך SUMMER יודפס לקונסולה . אני חושב שהדוגמה ברורה ואינה זקוקה להסבר.
Enum היא כיתה
על ידי הצהרהenum
, אנו יוצרים באופן מרומז מחלקה הנגזרת מ- java.lang.Enum
. באופן קונבנציונלי, הבנייה enum Season { ... }
שווה ערך ל class Season extends java.lang.Enum { ... }
. ולמרות שהמהדר לא מאפשר לנו לרשת מאיתנו במפורש java.lang.Enum
, עדיין קל לאמת enum
שהוא עבר בירושה באמצעות reflection
:
System.out.println(Season.class.getSuperclass());
הדברים הבאים יוצגו במסוף:
class java.lang.Enum
הירושה בפועל מבוצעת עבורנו אוטומטית על ידי מהדר Java. לאחר מכן, בואו נסכים לקרוא למחלקה שנוצרה על ידי המהדר כדי ליישם את הספירה בשם enum
-class, ואת הערכים האפשריים מהסוג המצוין כאלמנטים enum
-a.
איברי Enum הם מופעים enum
של -class הנגישים סטטית
אלמנטים enum Season (WINTER, SPRING и т.д.)
הם מופעים נגישים סטטית enum
של המחלקה Season
. הזמינות הסטטית שלהם מאפשרת לנו לבצע השוואות באמצעות אופרטור השוואת הפניות ==
. דוגמא:
Season season = Season.SUMMER;
if (season == Season.AUTUMN) season = Season.WINTER;
שם ומספר סידורי של אלמנט ה-enum
כפי שהוזכר קודם לכן, כלenum
מחלקה יורשת java.lang.Enum
, שמכילה מספר שיטות שימושיות עבור כל הספירות. דוגמא:
Season season = Season.WINTER;
System.out.println("season.name()=" + season.name() + " season.toString()=" + season.toString() + " season.ordinal()=" + season.ordinal());
הפלט יהיה:
season.name()=WINTER season.toString()=WINTER season.ordinal()=0
השיטות name()
, toString()
ומוצגות כאן ordinal()
. הסמנטיקה של השיטות ברורה. יש לציין ששיטות אלו enum
עוברות בירושה מהמחלקה java.lang.Enum
. קבלת אלמנט enum
לפי ייצוג המחרוזת של שמו. לעתים קרובות מתעוררת המשימה של קבלת אלמנט enum
לפי ייצוג המחרוזת שלו. למטרות אלו, בכל enum
מחלקה, המהדר יוצר אוטומטית שיטה סטטית מיוחדת: public static EnumClass valueOf(String name)
, המחזירה אלמנט ספירה EnumClass
עם שם השווה ל name
. דוגמה לשימוש:
String name = "WINTER";
Season season = Season.valueOf(name);
כתוצאה מביצוע הקוד, משתנה העונה יהיה שווה ל- Season.WINTER
. שים לב שאם האלמנט לא נמצא, ייזרק IllegalArgumentException , ואם הוא name
שווה null
, ייזרק NullPointerException . אגב, זה נשכח לעתים קרובות. מסיבה כלשהי, רבים משוכנעים בתוקף שאם פונקציה לוקחת ארגומנט אחד ובתנאים מסוימים זורקת IllegalArgumentException , אז כשמעבירים אותו לשם , null
בוודאי ייזרק גם IllegalArgumentException . אבל זה מעבר לעניין. בוא נמשיך. קבלת כל המרכיבים של ספירה לפעמים אתה צריך לקבל רשימה של כל האלמנטים enum
של -class בזמן ריצה. למטרות אלו, enum
המהדר יוצר שיטה בכל-class public static EnumClass[] values()
. דוגמה לשימוש:
System.out.println(Arrays.toString(Season.values()));
אנו מקבלים את הפלט הבא:
[WINTER, SPRING, SUMMER, AUTUMN]
שימו לב שלא שיטה valueOf()
ולא מתודה values()
מוגדרות במחלקה java.lang.Enum
. במקום זאת, הם מתווספים אוטומטית על ידי המהדר כאשר enum
ה--class מורכבת. הוספת שיטות משלך ל-- enum
class יש לך הזדמנות להוסיף שיטות משלך הן ל- enum
class והן לאלמנטים שלה: אותו הדבר, אבל עם פולימורפיזם: הדוגמה האחרונה מדגימה את השימוש בירושה ב- enum
. עוד על כך בהמשך. ירושהenum
ב- Java enum
מאפשרת ליישם היררכיית מחלקות, שהאובייקטים שלה נוצרים במופע בודד ונגישים סטטית. במקרה זה, אלמנטים enum
יכולים להכיל בנאים משלהם. בוא ניתן דוגמה: כאן אנו מכריזים על ספירה Type
עם שלושה אלמנטים INT
, INTEGER
ו STRING
. המהדר יצור את המחלקות והאובייקטים הבאים:
Type
- כיתה נגזרת מjava.lang.Enum
INT
- אובייקט של מחלקה 1 נגזרType
INTEGER
- אובייקט של מחלקה 2 נגזרType
STRING
- אובייקט של כיתה 3 נגזרType
Object parse(String)
ובנאי פולימורפית Type(..., boolean)
. יחד עם זאת, אובייקטים של מחלקות INT
, INTEGER
וקיימים STRING
בעותק בודד ונגישים סטטית. אתה יכול לאמת את זה:
System.out.println(Type.class);
System.out.println(Type.INT.getClass() + " " + Type.INT.getClass().getSuperclass());
System.out.println(Type.INTEGER.getClass() + " " + Type.INTEGER.getClass().getSuperclass());
System.out.println(Type.STRING.getClass() + " " + Type.STRING.getClass().getSuperclass());
אנו מקבלים את הפלט הבא:
class Type
class Type$1 class Type
class Type$2 class Type
class Type$3 class Type
ניתן לראות שהמהדר יצר מחלקה Type
ו-3 nested
מחלקות שנגזרו מ- Type
.
פירוק ה-enum-class עם ירושה
כדי לאשר את האמור לעיל, אנו מציגים גם את התוצאה של פירוק הספירהType
מהדוגמה לעיל:
ספירות ופולימורפיזם פרמטרי
הקורא עשוי לתהות: " מדוע ספירת הסוגים לעיל אינה משתמשת בגנריות? " העובדה היא שב-Java השימוש בגנריותenum
אסור. אז הדוגמה הבאה לא תתאים:
enum Type<T> {}
מחקר נוסף
להבנה מעמיקה יותר של אופן הפעולה של ספירות ב-Java, אני ממליץ לך להכיר את קוד המקור של הכיתהjava.lang.Enum
, ולהשתמש גם במפרקת Jad כדי ללמוד את הקוד שנוצר. יתרה מכך, לימוד קוד המקור של ספריית Java הוא הכרחי לחלוטין כדי להבין כמה מהמנגנונים ב-Java פועלים והוא שימושי כאסמכתא לעיצוב מונחה עצמים. קישור למקור המקורי: http://alexander.lds.lg.ua/
GO TO FULL VERSION