JavaRush /مدونة جافا /Random-AR /التعداد في جافا. أمثلة عملية. إضافة المنشئات والأساليب

التعداد في جافا. أمثلة عملية. إضافة المنشئات والأساليب

نشرت في المجموعة
مرحبًا! سنتحدث اليوم عن نوع خاص من البيانات في Java - 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 شهرا في التقويم. لدى Ocean 11 صديقًا فقط (على الرغم من أن هذا أمر قابل للنقاش :)) وبعبارة أخرى، فإن فئة Java العادية غير قادرة على تصميم هذه الكيانات واحترام قيودها الطبيعية. صفنا Monthلديه كل المجالات اللازمة. ولكن إذا استخدمه مبرمج آخر، فلن يمنعه أحد من إنشاء كائنات مجنونة تمامًا:
public class Main {

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

}
إذا ظهر هذا في البرنامج فلن يكون من السهل العثور على الجاني! من ناحية، كان من الممكن للمبرمج الذي أنشأ الكائنات أن يفهم أن الفصل Monthيعني "شهر العام" ولم يكتب مثل هذا الهراء. ومن ناحية أخرى، كان يستغل فقط الفرص التي قدمها له مصمم الفصل. هل يمكنني تعيين أي أسماء وعدد الأيام؟ لقد عينه. ماذا تفعل في مثل هذه الحالة؟ قبل إصدار الإصدار 1.5 من لغة Java، كان على المبرمجين، بصراحة، الخروج منه :) في تلك الأيام، قاموا بإنشاء التركيبات التالية:
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 مشكلة موجودة. بالطبع، من الرائع أن يتمكن المبرمجون من التوصل إلى حل باستخدام الأدوات المتوفرة في اللغة، لكن الأمر لا يبدو بهذه البساطة! وكانت هناك حاجة إلى حل واضح، يمكن الوصول إليه حتى للمبتدئين. هكذا ظهر في جافا 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هذا فصل دراسي كامل. هذا يعني أنه إذا لزم الأمر، يمكنك تحديد المنشئات والأساليب فيه. على سبيل المثال، في الجزء السابق من التعليمات البرمجية قمنا ببساطة بتحديد القيم يناير، فبراير، مارس. ومع ذلك، يمكننا توسيع نطاقنا 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 +
               '}';
   }
}
لقد أضفنا هنا حقلين إلى حقلنا enum- اسم الشهر وعدد الأيام، ومنشئ يستخدم هذه الحقول، ومحددات الحروف، وطريقة toString()، بالإضافة إلى طريقتين ثابتتين. كما ترون، لم تكن هناك مشاكل في هذا: كما قلنا سابقًا، 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}]
أخيرًا، أود أن أرشح لك كتابًا مفيدًا للغاية عن Java، وهو "Effective Java" بقلم جوشوا بلوخ . التعداد.  أمثلة عملية.  إضافة المنشئات والأساليب - 3المؤلف هو أحد مبدعي Java، لذا يمكنك بالتأكيد الوثوق بنصيحته بشأن الاستخدام الصحيح والكفء لأدوات اللغة :) فيما يتعلق بمحاضرتنا، أنصحك بإيلاء اهتمام خاص للفصل المخصص لـ enum. هل لديك قراءة مثمرة! :)
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION