JavaRush /Java blogi /Random-UZ /Java tilidagi enum. Amaliy misollar. Konstruktorlar va us...

Java tilidagi enum. Amaliy misollar. Konstruktorlar va usullarni qo'shish

Guruhda nashr etilgan
Salom! Bugun biz Java-da maxsus ma'lumotlar turi haqida gaplashamiz - Enum(hisoblash uchun qisqacha). Ularning xususiyati nimada? Tasavvur qilaylik, dasturda oylarni amalga oshirishimiz kerak. Enum.  Amaliy misollar.  Konstruktorlar va usullarni qo'shish - 1Ko'rinib turibdiki, muammo nimada? Faqat har qanday oyda qanday xususiyatlarga ega ekanligini aniqlash kerak. Ehtimol, bizga, birinchi navbatda, oyning nomi va undagi kunlar soni kerak. Muammoni hal qilish juda oddiy ko'rinadi:
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 +
               '}';
   }
}
Iltimos, to'liq to'plam! Bizda sinf mavjud Month, kerakli maydonlar, getters-setters, toString(). equals()To'liq baxt uchun uni qo'shish kerak bo'lmasa hashCode():) Biroq, bizda kontseptual muammo bor. Esingizda bo'lsa, OOP ning asosiy afzalliklaridan biri shundaki, u haqiqiy ob'ektlarni modellashtirishni osonlashtiradi. Kreslo, mashina, sayyora - bu kundalik hayotdagi barcha tushunchalarni abstraktsiya yordamida dasturda tasvirlash oson. Muammo shundaki, real dunyodagi ba'zi ob'ektlar qat'iy cheklangan ma'noga ega. Bir yilda atigi 4 fasl bor. Musiqada faqat 7 ta nota mavjud. Kalendarda atigi 12 oy bor. Okeanning atigi 11 do'sti bor (garchi bu bahsli bo'lsa-da :)) Boshqacha qilib aytganda, oddiy Java sinfi bu ob'ektlarni modellashtirishga va ularning tabiiy cheklovlarini hurmat qilishga qodir emas. Bizning sinfda Monthbarcha kerakli maydonlar mavjud. Ammo agar boshqa dasturchi undan foydalansa, hech kim uni butunlay aqldan ozgan narsalarni yaratishga to'sqinlik qilmaydi:
public class Main {

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

}
Agar bu dasturda paydo bo'lsa, aybdorni topish oson bo'lmaydi! Bir tomondan, ob'ektlarni yaratgan dasturchi sinf Month"yil oyi" degan ma'noni anglatishini tushunishi va bunday bema'ni narsalarni yozmasligi mumkin edi. Boshqa tomondan, u sinf dizayneri unga taqdim etgan imkoniyatlardan shunchaki foydalandi. Har qanday nom va kunlar sonini belgilashim mumkinmi? U tayinladi. Bunday vaziyatda nima qilish kerak? Java tilining 1.5 versiyasi chiqarilishidan oldin dasturchilar, ochig'ini aytganda, undan chiqib ketishlari kerak edi :) O'sha kunlarda ular quyidagi konstruktsiyalarni yaratdilar:
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 +
               '}';
   }
}
Bu erda biz misolni qisqartirish uchun oylar sonini o'n ikki o'rniga uchga soddalashtirdik. Bunday dizaynlar muammoni hal qilish imkonini berdi. Yaratilgan ob'ektlar uchun imkoniyatlar xususiy konstruktor tomonidan cheklangan:
private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }
Sinfdan foydalanadigan dasturchilar shunchaki yarata olmadilar Month. Ular sinf ishlab chiqaruvchisi tomonidan taqdim etilgan oxirgi statik ob'ektlardan foydalanishga majbur bo'lishdi. Bu shunday ko'rinardi:
public class Main {

   public static void main(String[] args) {

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

}
Biroq, Java dasturchilari mavjud muammoni payqashdi. Albatta, dasturchilar tilda mavjud vositalar yordamida yechim topishga muvaffaq bo'lgani juda yaxshi, lekin bu unchalik oddiy ko'rinmaydi! Hatto yangi boshlanuvchilar uchun ham ochiq yechim kerak edi. Java'da shunday paydo bo'ldi Enum. Aslida, Enumbu cheklangan qiymatli ob'ektlar to'plamini ta'minlovchi Java sinfidir. Bu qanday ko'rinishga ega:
public enum Month {

   JANUARY,
   FEBRUARY,
   MARCH
}
Ta'rifda biz Enumbu Java klassi ekanligini ko'rsatdik, ammo bu haqiqatmi? Ha, va biz buni hatto tekshira olamiz. Masalan, biznikini enum Monthboshqa sinfdan meros qilib ko'ring:
public abstract class AbstractMonth {
}

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

   JANUARY,
   FEBRUARY,
   MARCH
}
Nima uchun bu sodir bo'lmoqda? Biz dasturga yozganimizda:
public enum Month
Kompilyator ushbu buyruqni quyidagi kodga aylantiradi:
public Class Month extends Enum
Ma'lumki, Java-da bir nechta merosga ruxsat berilmaydi. Shuning uchun AbstractMonthbiz merosxo'rlik qila olmadik. Ushbu yangi dizayndan qanday Enumfoydalanish mumkin? Va maydonlar bilan eski dizayndan qanday farq qiladi static final? Masalan, eski dizayn bizga o'z qadriyatlarimiz to'plamidan switch- ifodalarda foydalanishga imkon bermadi. Tasavvur qiling-a, biz bu oy qanday bayramlar nishonlanishini eslatuvchi dastur yaratmoqchimiz:
public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {

           //error!
           case JANUARY:
       }
   }
}
Bu erda, ko'rib turganingizdek, kompilyator xatoga yo'l qo'yadi. Ammo Java 1.5 paydo bo'lgandan keyin enumhamma narsa ancha soddalashdi:
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);

   }

}
Konsol chiqishi:

7 января будет Рождество!
Iltimos, diqqat qiling: ob'ektlarga kirish EnumJava 1.5 dan oldin bo'lgani kabi statik bo'lib qoladi. MonthOylarga kirish uchun ob'ekt yaratishimiz shart emas . EnumRo'yxatlar bilan ishlashda, bu to'liq huquqli sinf ekanligini unutmaslik juda muhimdir . Bu shuni anglatadiki, agar kerak bo'lsa, unda konstruktorlar va usullarni belgilashingiz mumkin. Masalan, oldingi kod qismida biz oddiygina YANVAR, FEVRAL, MART qiymatlarini ko'rsatdik. Biroq, biz o'zimizni enum Monthquyidagicha kengaytirishimiz mumkin:
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 +
               '}';
   }
}
Bu erda biz o'zimizga 2 ta maydon qo'shdik enum- oy nomi va kunlar soni, ushbu maydonlardan foydalanadigan konstruktor, getters-setters, usul toString(), shuningdek, 2 ta statik usul. Ko'rib turganingizdek, bu bilan hech qanday muammo yo'q edi: yuqorida aytib o'tganimizdek, enumbu to'liq huquqli sinf:
import java.util.Arrays;

public class Main {

   public static void main(String[] args) {

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

   }

}
Konsol chiqishi:

[Month{name='Июнь', daysCount=30}, Month{name='Июль', daysCount=31}, Month{name='Август', daysCount=31}]
Va nihoyat, men sizga Java bo'yicha juda foydali kitobni tavsiya qilmoqchiman, ya'ni Joshua Blochning "Effektiv Java" kitobi . Enum.  Amaliy misollar.  Konstruktorlar va usullarni qo'shish - 3Muallif Java-ni yaratuvchilardan biridir, shuning uchun siz uning til vositalaridan to'g'ri va malakali foydalanish bo'yicha maslahatlariga shubhasiz ishonishingiz mumkin :) Bizning ma'ruzamiz bilan bog'liq holda, kitobning ga bag'ishlangan bobiga alohida e'tibor berishingizni maslahat beraman enum. O'qishni samarali o'tkazing! :)
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION