Wyliczenia na sterydach

2007-12-28 21:57

Co można powiedzieć o typach wyliczeniowych (enums)? Choćby to, że przydają się tam, gdzie mamy do czynienia ze stanami lub atrybutami, które należą do jakiegoś skończonego zbiory. Z technicznego punktu widzenia to kilka(naście/dziesiąt/set) liczb nazwanych stałymi identyfikatorami. I zazwyczaj języki programowania nie oferują wiele ponad to.
Lecz Java musiała się tu wyróżnić :) Z wierzchu jej enumy wyglądają niby zwyczajnie:

  1. public enum Answer { YES, NO, DONT_KNOW, DONT_CARE }

ale w środku kryją bardzo szerokie i pewnie trochę udziwnione możliwości…

Zacznijmy od tego, że takie stałe wyliczeniowe są bezpieczne pod względem typowania – nie można więc jawnie rzutować ich na zwykłe liczby typu int. Słowo kluczowe enum tworzy też – podobnie jak w C# – przestrzeń nazw, więc do stałych odwołujemy się nazwami kwalifikowanymi (Answer.YES) i nie trzeba stosować żadnych przedrostków.
Ale to są wręcz oczywistości. Kolejnym punktem programu jest możliwość dostępu do zbioru zadeklarowanych stałych oraz ich wypisywania w postaci tekstowych nazw:

  1. System.out.println ("[Poll] Are enums in Java too exaggerated?");
  2. for (Answer answer : Answer.values())
  3.    System.out.printf ("( ) %s\n", answer);

Takie nazwy mogą być jednak brzydkie. Żaden problem, bowiem w Javie z każdą stałą może być związany dowolny zestaw danych:

  1. public enum Answer
  2. {
  3.    YES("Yes"), NO("No"), DONT_KNOW("I don't know"), DONT_CARE("I don't care");
  4.  
  5.    // deklaracja dodatkowych danych w postaci pól
  6.    private final String message;
  7.  
  8.    // konstruktor (!)
  9.    Answer(String message)   { this.message = message; }
  10.  
  11.    // metoda dostępowa
  12.    public String getMessage()   { return message; }
  13. }

które – jak widać – deklarujemy podobnie jak składniki klas. A poszczególne “stałe” typu wyliczeniowego nie są już na pewno tylko liczbami: to pelnoprawne obiekty:

  1. System.out.println ("[Poll] Is this poll much better?");
  2. for (Answer answer : Answer.values())
  3.    System.out.printf ("( ) %s\n", answer.getMessage());

Widzimy, że metody są również dozwolone. Żeby było śmieszniej, mogą być one nawet “wirtualne”. Możemy bowiem zapewnić, aby inne ich wersje były wywoływane dla różnych stałych. Robi wrażenie, prawda?…

Cóż, pewnie niekoniecznie – zwłaszcza, że nietrudno osiągnąć podobną funkcjonalność przez instrukcję wyboru. Zgoda, będzie ona bardziej podatna i trudniejsza w konserwacji. Lecz jeśli alternatywą jest przeładowanie języka dziwnymi i nie do końca oczywistymi mechanizmami, to stary dobry switch niekoniecznie musi być rozwiązaniem złym.
Co oczywiście nie zabrania nam być pod wrażeniem pomysłowości twórców języka Java :-)

Tags: ,
Author: Xion, posted under Programming »


12 comments for post “Wyliczenia na sterydach”.
  1. brodny:
    December 28th, 2007 o 22:52

    Nie string, a String ;)

  2. Xion:
    December 29th, 2007 o 0:03

    True. Ale nie zmienia to faktu, że GeSHi coś słabo sobie radzi z kolorowaniem tych wynalazków z Javy nr 5 :)

  3. Jacek Złydach, TeMPOraL:
    December 29th, 2007 o 0:32

    “(…) takie stałe wyliczeniowe są bezpieczne pod względem typowania – nie można więc jawnie rzutować ich na zwykłe liczby typu int. (…) Ale to są wręcz oczywistości.”
    Nie bardzo rozumiem, dlaczego niemożność konwersji enum->int jest oczywistością ;).

  4. Xion:
    December 29th, 2007 o 9:26

    Bo tylko w C++ enumy to niemal to samo co liczby, podczas gdy faktycznie są to tylko skończone zbiory, które mogą reprezentować cokolwiek. To, że akurat wszyscy przyzwyczaili się, że “w środku” są to liczby, nie zawsze musi być prawdą (Java to pokazuje). I nawet jeśli jest, nie powinno się tak łatwo konwertować je na liczby.

  5. Kurak:
    December 29th, 2007 o 11:40

    Nie wiem czemu, ale wydaje mi się to trochę przekombinowane. Ale nie znam zbyt dobrze Javy, więc pewnie tylko mi się wydaje ;)

  6. brodny:
    December 29th, 2007 o 14:34

    Czemu przekombinowane? To ma być enum i tę funkcję pełni dobrze. A dodatkowych bajerów używać nie musisz :)

  7. Crane:
    December 29th, 2007 o 20:40

    @brodny dokładnie
    Funkcja enumów spełniona, a te bajery z enumów parę razy mi się przydały, więc nie marudzić.

    Takie fajne enumy wyszły im właściwie przez przypadek. Wprowadzono je dopiero w Javie 1.5, a Sun ma zasadę, że kod jest kompatybilny z poprzednimi wersjami, więc musiano użyć jakiegoś już istniejącego elementu języka. Enum jest w rzeczywistości klasą (kompiluje sie do *.class).

  8. Xion:
    December 29th, 2007 o 20:45

    Co powoduje, że trzeba każdego – nawet najmniejszego enuma – deklarować w osobnym pliku. No ale to jest generalna przypadłość Javy :)

  9. Crane:
    December 29th, 2007 o 20:57

    Ale to też powoduje, że mam przejrzysty podział na klasy i że się nie gubię w kodzie źródłowym :)
    Ja w każdym języku stosuje się do trzymania jednej klasy w jednym pliku.

  10. Kurak:
    December 31st, 2007 o 12:18

    Nie nazwałbym wymuszania deklaracji enuma w oddzielnym pliku przejrzystym podziałem :P

  11. Jarek Przygódzki:
    October 4th, 2010 o 22:04

    Już rzut oka na definicję klasy bazowej dla typów wyliczeniowych w Javie wskazuje dobitnie, że należy je traktować poważnie

    public abstract class Enum<E extends Enum>
    implements Comparable, Serializable {

    }

  12. Jarek Przygódzki:
    October 4th, 2010 o 22:07

    @Kurak
    Nikt nie wymusza deklaracji enuma w oddzielnym pliku.

Comments are disabled.
 


© 2017 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.