CodeGym /Blog Java /Random-PL /wylicz. Praktyczne przykłady. Dodawanie konstruktorów i m...
Autor
Alex Vypirailenko
Java Developer at Toshiba Global Commerce Solutions

wylicz. Praktyczne przykłady. Dodawanie konstruktorów i metod

Opublikowano w grupie Random-PL
Cześć! Dzisiaj porozmawiamy o jednym ze specjalnych typów danych w Javie: Enum(skrót od „enumeration”). Co czyni go wyjątkowym? Wyobraźmy sobie, czego potrzebujemy, aby zaimplementować „miesiące” w programie. wylicz.  Praktyczne przykłady.  Dodawanie konstruktorów i metod - 1 Nie wydaje się problematyczne, prawda? Musimy tylko określić, jakie właściwości ma dany miesiąc. Być może najpierw potrzebujemy nazwy miesiąca i liczby dni w nim zawartych. Rozwiązanie wygląda dość prosto:

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 +
               '}';
   }
}
Cały szaban! Mamy Monthklasę, wymagane pola, pobierające/ustawiające i toString(). O ile oczywiście nie musimy dodać equals()ihashCode()osiągnąć pełnię szczęścia :) Ale tutaj mamy problem pojęciowy. Jak zapewne pamiętasz, jedną z głównych zalet OOP jest to, że ułatwia modelowanie obiektów z rzeczywistego świata. Krzesło, samochód, planeta — wszystkie te pojęcia ze zwykłego życia można łatwo przedstawić w programie za pomocą abstrakcji. Problem polega na tym, że niektóre byty w świecie rzeczywistym mają ściśle ograniczony zakres wartości. W roku są tylko 4 pory roku. W oktawie jest tylko 8 nut. Kalendarz ma tylko 12 miesięcy. A Danny Ocean z Ocean's 11 ma tylko 11 przyjaciół (choć to nie ma znaczenia :)) Liczy się to, że zwykła klasa Javy nie jest w stanie modelować tych bytów i narzucać ich naturalnych ograniczeń. NaszMonthclass ma wszystkie wymagane pola. Ale jeśli użyje go inny programista, nikt nie może go powstrzymać przed tworzeniem całkowicie szalonych obiektów:

public class Main {

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

}
Jeśli pojawi się to w naszym kodzie, nie będzie łatwo znaleźć winowajcę! Z jednej strony programista tworzący obiekty mógłby sobie uświadomić, że Monthklasa oznacza „miesiąc w roku” i nie pisać takich bzdur. Z drugiej strony programista korzysta tylko z możliwości, które zapewnia projektant klasy. Czy można nadawać dowolne nazwy i numery dni? Dokładnie to mamy. Co w takim razie powinniśmy zrobić w tej sytuacji? Szczerze mówiąc, zanim wypuszczono Javę 1.5, programiści musieli wykazać się kreatywnością :) W tamtych czasach tworzyli takie struktury:

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 +
               '}';
   }
}
Tutaj skróciliśmy liczbę miesięcy z dwunastu do trzech, aby skrócić przykład. Takie projekty umożliwiły rozwiązanie problemu. Możliwość tworzenia obiektów została ograniczona do prywatnego konstruktora:

private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }
Programiści korzystający z tej klasy nie mogli po prostu tworzyć Monthobiektów. Musieli użyć ostatecznych obiektów statycznych dostarczonych przez twórcę klasy. Na przykład tak:

public class Main {

   public static void main(String[] args) {

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

}
Jednak programiści Java zwrócili uwagę na istniejący problem. Oczywiście to wspaniale, że programiści byli w stanie wymyślić rozwiązanie przy użyciu narzędzi dostępnych w języku, ale nie wygląda to na takie proste! Potrzebne było oczywiste rozwiązanie, nawet dla nowicjuszy. I tak Enumpojawił się w Javie. Zasadniczo Enumjest to klasa Java, która zapewnia ograniczony zestaw wartości obiektów. Oto jak to wygląda:

public enum Month {
  
   JANUARY,
   FEBRUARY,
   MARCH
}
W definicji wskazaliśmy, że Enumjest to klasa Java, ale czy to naprawdę prawda? Tak, a nawet możemy to zweryfikować. Na przykład spróbuj sprawić, by nasze Monthwyliczenie odziedziczyło inną klasę:

public abstract class AbstractMonth {
}

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

   JANUARY,
   FEBRUARY,
   MARCH
}
Dlaczego tak się dzieje? Kiedy piszemy:

public enum Month
kompilator konwertuje tę instrukcję na następujący kod:

public Class Month extends Enum
Jak już wiesz, Java nie obsługuje wielokrotnego dziedziczenia. Dlatego nie możemy dziedziczyć AbstractMonth. EnumJak można wykorzystać ten nowy konstrukt, ,? I czym różni się od starego konstruktu z static finalpolami? Cóż, na przykład stara konstrukcja nie pozwalała nam używać własnego zestawu wartości w switchinstrukcjach. Wyobraź sobie, że chcemy stworzyć program, który będzie nam przypominał o świętach obchodzonych w każdym miesiącu:

public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {

           // Error!
           case JANUARY:
       }
   }
}
Jak widać, kompilator wyrzuca tutaj błąd. Ale kiedy enumpojawił się w Javie 1.5, wszystko stało się znacznie prostsze:

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);

   }

}
Wyjście konsoli:

New Year's Day is January 1st!
Należy zauważyć, że dostęp do Enumobiektów pozostał statyczny, tak jak przed Javą 1.5. Nie musimy tworzyć Monthobiektu, aby uzyskać dostęp do miesięcy. Podczas pracy z wyliczeniami bardzo ważne jest, aby nie zapominać, że Enumjest to pełnoprawna klasa. Oznacza to, że w razie potrzeby można w nim zdefiniować konstruktory i metody. Na przykład w poprzednim fragmencie kodu po prostu określiliśmy wartości: JANUARY, FEBRUARY, MARCH. Możemy jednak rozszerzyć nasze Monthwyliczenie w następujący sposób:

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 +
               '}';
   }
}
Tutaj podaliśmy nasze enum2 pola (nazwę miesiąca i liczbę dni), konstruktor korzystający z tych pól, getter/settery, metodę toString()i 2 metody statyczne. Jak widać, nie było z tym żadnych problemów. Ponownie, Enumnaprawdę jest pełnoprawną klasą:

import java.util.Arrays;

public class Main {

   public static void main(String[] args) {

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

   }

}
Wyjście konsoli:

[Month{name='June', daysCount=30}, Month{name='July', daysCount=31}, Month{name='August', daysCount=31}]
Na koniec chcę polecić niezwykle przydatną książkę o Javie, a mianowicie „Efektywna Java” autorstwa Joshua Blocha . wylicz.  Praktyczne przykłady.  Dodawanie konstruktorów i metod - 3Autor jest jednym z twórców Javy, więc zdecydowanie możesz zaufać jego radom, jak poprawnie i kompetentnie korzystać z narzędzi języka :) W odniesieniu do naszej lekcji, polecam zwrócić szczególną uwagę na rozdział książki pt Enum. Miłej lektury! :)
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION