здрасти Днес ще говорим за един от специалните типове данни на Java:
Не изглежда проблемно, нали? Просто трябва да определим Howви свойства има всеки месец. Може би първо се нуждаем от името на месеца и броя на дните в него. Решението изглежда доста просто:
Authorът е един от създателите на Java, така че определено можете да се доверите на съветите му How правилно и компетентно да използвате инструментите на езика :) По отношение на нашия урок ви препоръчвам да обърнете специално внимание на главата на книгата за
Enum
(съкратено от „изброяване“). Какво го прави специален? Нека си представим Howво ни трябва, за да внедрим „месеци“ в една програма. ![Enum. Практически примери. Добавяне на конструктори и методи – 1](https://cdn.codegym.cc/images/article/778a9e3e-3c9f-495e-a613-f9eec6c733b9/800.jpeg)
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/setter и toString()
. Освен ако, разбира се, не трябва да добавим equals()
иhashCode()
за постигане на пълно щастие :) Но тук имаме концептуален проблем. Както вероятно си спомняте, едно от основните предимства на ООП е, че улеснява моделирането на обекти от реалния свят. Стол, кола, планета - всички тези концепции от обикновения живот лесно се представят в програма с помощта на абстракция. Проблемът е, че някои обекти от реалния свят имат строго ограничен диапазон от стойности. Има само 4 сезона в годината. Има само 8 ноти в една октава. Календарът има само 12 месеца. И Дани Оушън от 11 на Оушън има само 11 приятели (въпреки че това няма meaning :)) Това, което има meaning е, че един обикновен Java клас не е в състояние да моделира тези обекти и да наложи естествените им ограничения. НашитеMonth
има всички задължителни полета. Но ако друг програмист го използва, никой не може да го спре да създава напълно безумни обекти:
public class Main {
Month month1 = new Month("lolkek", 322);
Month month2 = new Month("yahoooooooooooo", 12345);
}
Ако това се появи в нашия code, няма да е лесно да открием виновника! От една страна, програмистът, който създава обектите, може да осъзнае, че класът 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
се появи в Java. По принцип Enum
е Java клас, който предоставя ограничен набор от обектни стойности. Ето How изглежда:
public enum Month {
JANUARY,
FEBRUARY,
MARCH
}
В дефиницията посочихме, че това Enum
е Java клас, но наистина ли е вярно? Да, и дори можем да го проверим. Например, опитайте да накарате нашия Month
enum да наследи няHowъв друг клас:
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
компилаторът преобразува този оператор в следния code:
public Class Month extends Enum
Както вече знаете, Java не поддържа множествено наследяване. Следователно не можем да наследим AbstractMonth
. Enum
Как може да се използва тази нова конструкция ? И How се различава от старата конструкция с 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
обекти остава статичен, точно Howто беше преди Java 1.5. Не е необходимо да създаваме Month
обект за достъп до месеците. Когато работите с enum, е много важно да не забравяте, че това Enum
е пълноценен клас. Това означава, че при необходимост можете да дефинирате конструктори и методи в него. Например в предишния codeов фрагмент ние просто посочихме стойностите: ЯНУАРИ, ФЕВРУАРИ, МАРТ. Въпреки това можем да разширим нашия Month
enum по следния начин:
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
2 полета (името на месеца и броя на дните), конструктор, който използва тези полета, getter/setter, метода 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}]
И накрая, искам да препоръчам една изключително полезна книга за Java, а именно „Ефективна Java“ от Джошуа Блок . ![Enum. Практически примери. Добавяне на конструктори и методи – 3](https://cdn.codegym.cc/images/article/924d6795-0c65-4050-9bed-db26dd2be3ef/800.jpeg)
Enum
. Приятно четене! :)
GO TO FULL VERSION