CodeGym /وبلاگ جاوا /Random-FA /Enum. نمونه های عملی اضافه کردن سازنده ها و روش ها
John Squirrels
مرحله
San Francisco

Enum. نمونه های عملی اضافه کردن سازنده ها و روش ها

در گروه منتشر شد
سلام! امروز در مورد یکی از انواع داده های خاص جاوا صحبت خواهیم کرد: Enum(مخفف عبارت "Enumeration"). چه چیزی آن را خاص می کند؟ بیایید تصور کنیم که برای پیاده سازی «ماه» در یک برنامه به چه چیزی نیاز داریم. 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کلاس، فیلدهای مورد نیاز، getter/setters و toString(). مگر اینکه ما نیاز به اضافه کردن داشته باشیم equals()و hashCode()به شادی کامل برسیم :) اما اینجا یک مشکل مفهومی داریم. همانطور که احتمالاً به خاطر دارید، یکی از مزایای اصلی OOP این است که مدل سازی موجودیت ها از دنیای واقعی را آسان می کند. یک صندلی، یک ماشین، یک سیاره - همه این مفاهیم از زندگی عادی به راحتی در یک برنامه با کمک انتزاع نمایش داده می شوند. مشکل این است که برخی از موجودیت‌های دنیای واقعی دارای محدوده محدودی از مقادیر هستند. فقط 4 فصل در سال وجود دارد. فقط 8 نت در یک اکتاو وجود دارد. تقویم فقط 12 ماه دارد. و Danny Ocean of Ocean's 11 فقط 11 دوست دارد (اگرچه این مهم نیست :)) آنچه مهم است این است که یک کلاس جاوای معمولی قادر به مدل سازی این موجودات و اعمال محدودیت های طبیعی آنها نیست. کلاس ما Monthتمام فیلدهای مورد نیاز را دارد. اما اگر برنامه نویس دیگری از آن استفاده کند، هیچ کس نمی تواند او را از ایجاد اشیاء کاملاً دیوانه منع کند:
public class Main {

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

}
اگر این در کد ما ظاهر شود، پیدا کردن مقصر کار آسانی نخواهد بود! از یک طرف، برنامه نویسی که اشیاء را ایجاد می کند ممکن است متوجه شود که Monthکلاس به معنای "ماه در سال" است و چنین مزخرفاتی را ننویسد. از سوی دیگر، برنامه نویس تنها از توانایی هایی استفاده می کند که طراح کلاس ارائه کرده است. آیا امکان تعیین نام و تعداد روز دلخواه وجود دارد؟ این دقیقاً همان چیزی است که ما به دست آوردیم. پس در این شرایط باید چکار کنیم؟ راستش قبل از انتشار جاوا 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);
   }

}
اما توسعه دهندگان جاوا به مشکل موجود توجه کردند. البته خیلی خوب است که برنامه نویسان توانستند با استفاده از ابزارهای موجود در این زبان راه حلی ارائه دهند، اما به نظر چندان آسان نیست! حتی برای تازه کارها به یک راه حل واضح نیاز بود. و به این ترتیب Enumدر جاوا ظاهر شد. اساساً Enumیک کلاس جاوا است که مجموعه محدودی از مقادیر شی را فراهم می کند. در اینجا به نظر می رسد:
public enum Month {

   JANUARY,
   FEBRUARY,
   MARCH
}
در تعریف، ما نشان دادیم که Enumیک کلاس جاوا است، اما آیا این واقعاً درست است؟ بله، و ما حتی می توانیم آن را تأیید کنیم. برای مثال، سعی کنید Monthenum ما کلاس دیگری را به ارث ببرد:
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در جاوا 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اشیا مانند قبل از جاوا 1.5 ثابت باقی می ماند. Monthبرای دسترسی به ماه ها نیازی به ایجاد یک آبجکت نداریم . هنگام کار با enums، بسیار مهم است که فراموش نکنید که Enumیک کلاس تمام عیار است. یعنی در صورت لزوم می توانید سازنده ها و متدهایی را در آن تعریف کنید. به عنوان مثال، در قطعه کد قبلی، ما به سادگی مقادیر را مشخص کردیم: JANUARY، FEBRUARY، MARCH. با این حال، ما می توانیم 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 +
               '}';
   }
}
در اینجا ما enum2 فیلد خود را (نام ماه و تعداد روزها)، سازنده ای که از این فیلدها، getter/setters، متد 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='June', daysCount=30}, Month{name='July', daysCount=31}, Month{name='August', daysCount=31}]
در نهایت، من می خواهم یک کتاب جاوا بسیار مفید، یعنی "جاوای موثر" اثر جاشوا بلوخ را توصیه کنم . Enum.  نمونه های عملی  افزودن سازنده ها و روش ها - 3نویسنده یکی از خالقان جاوا است، بنابراین می توانید به توصیه های او در مورد نحوه استفاده صحیح و شایسته از ابزارهای زبان مطمئن باشید :) در مورد درس ما، توصیه می کنم به فصل کتاب توجه ویژه ای داشته باشید Enum. خواندن مبارک! :)
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION