CodeGym /مدونة جافا /Random-AR /التعداد. أمثلة عملية. إضافة المنشئات والأساليب
John Squirrels
مستوى
San Francisco

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

نشرت في المجموعة
أهلاً! سنتحدث اليوم عن أحد أنواع البيانات الخاصة بجافا: Enum(اختصار لـ "enumeration"). ما الذي يجعلها مميزة؟ دعونا نتخيل ما نحتاجه لتنفيذ "الأشهر" في البرنامج. التعداد.  أمثلة عملية.  إضافة المنشئات والأساليب - 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فئة، والحقول المطلوبة، وgetter/setters، و toString(). ما لم يكن، بالطبع، بحاجة إلى إضافة equals()وتحقيق hashCode()السعادة الكاملة :) ولكن هنا لدينا مشكلة مفاهيمية. كما تتذكر على الأرجح، إحدى المزايا الرئيسية لـ OOP هي أنها تجعل من السهل نمذجة الكيانات من العالم الحقيقي. كرسي، سيارة، كوكب - كل هذه المفاهيم من الحياة العادية يمكن تمثيلها بسهولة في البرنامج بمساعدة التجريد. المشكلة هي أن بعض كيانات العالم الحقيقي لديها نطاق محدود للغاية من القيم. هناك 4 مواسم فقط في السنة. هناك 8 نغمات فقط في الأوكتاف. التقويم لديه 12 شهرا فقط. ولدى داني أوشن أوف أوشن 11 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("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 +
               '}';
   }
}
وقد قمنا هنا بتخفيض عدد الأشهر من اثني عشر شهرًا إلى ثلاثة لكي يكون المثال أقصر. مثل هذه التصاميم جعلت من الممكن حل المشكلة. كانت القدرة على إنشاء الكائنات مقتصرة على منشئ خاص:
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، ولكن هل هذا صحيح حقًا؟ نعم، ويمكننا حتى التحقق من ذلك. على سبيل المثال، حاول جعل التعداد الخاص بنا Monthيرث فئة أخرى:
public abstract class AbstractMonth {
}

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

   JANUARY,
   FEBRUARY,
   MARCH
}
لماذا يحدث ذلك؟ عندما نكتب:
public enum Month
يقوم المترجم بتحويل هذا البيان إلى الكود التالي:
public Class Month extends Enum
كما تعلم، جافا لا تدعم الوراثة المتعددة. ولذلك، لا يمكننا أن نرث AbstractMonth. Enumكيف يمكن استخدام هذا البناء الجديد ؟ وكيف يختلف عن البناء القديم مع static finalالحقول؟ حسنًا، على سبيل المثال، لم يسمح لنا البناء القديم باستخدام مجموعة القيم الخاصة بنا في switchالبيانات. تخيل أننا نريد إنشاء برنامج يذكرنا بالأعياد التي يتم الاحتفال بها كل شهر:
public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {

           // Error!
           case JANUARY:
       }
   }
}
كما ترون، المترجم يلقي خطأ هنا. ولكن بمجرد enumظهور Java 1.5، أصبح كل شيء أبسط بكثير:
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);

   }

}
إخراج وحدة التحكم:

New Year's Day is January 1st!
لاحظ أن الوصول إلى Enumالكائنات ظل ثابتًا، تمامًا كما كان قبل Java 1.5. لا نحتاج إلى إنشاء Monthكائن للوصول إلى الأشهر. عند العمل مع التعدادات، من المهم جدًا ألا ننسى أن Enumهذه فئة كاملة. هذا يعني أنه إذا لزم الأمر، يمكنك تحديد المنشئات والأساليب فيه. على سبيل المثال، في جزء التعليمات البرمجية السابق، قمنا ببساطة بتحديد القيم: يناير، فبراير، مارس. ومع ذلك، يمكننا توسيع Monthالتعداد لدينا مثل هذا:
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 +
               '}';
   }
}
لقد قدمنا ​​هنا enumحقلين (اسم الشهر وعدد الأيام)، ومُنشئ يستخدم هذه الحقول، وgetter/setters، والطريقة toString()، وطريقتين ثابتتين. كما ترون، لم تكن هناك مشاكل مع هذا. مرة أخرى، Enumإنها حقًا فئة كاملة:
import java.util.Arrays;

public class Main {

   public static void main(String[] args) {

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

   }

}
إخراج وحدة التحكم:

[Month{name='June', daysCount=30}, Month{name='July', daysCount=31}, Month{name='August', daysCount=31}]
أخيرًا، أود أن أوصي بكتاب Java مفيد للغاية، وهو "Effective Java" بقلم جوشوا بلوخ . التعداد.  أمثلة عملية.  إضافة المنشئات والأساليب - 3المؤلف هو أحد المبدعين في Java، لذلك يمكنك بالتأكيد الوثوق بنصيحته حول كيفية استخدام أدوات اللغة بشكل صحيح وكفء :) فيما يتعلق بدرسنا، أوصي بإيلاء اهتمام خاص للفصل الذي يتناول Enum. قراءة سعيدة! :)
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION