CodeGym /Blog Java /Aleatoriu /Enum. Exemple practice. Adăugarea de constructori și meto...
John Squirrels
Nivel
San Francisco

Enum. Exemple practice. Adăugarea de constructori și metode

Publicat în grup
Bună! Astăzi vom vorbi despre unul dintre tipurile speciale de date Java: Enum(prescurtare de la „enumerare”). Ce îl face special? Să ne imaginăm de ce avem nevoie pentru a implementa „luni” într-un program. Enum.  Exemple practice.  Adăugarea de constructori și metode - 1 Nu pare problematic, nu? Trebuie doar să stabilim ce proprietăți are fiecare lună. Poate că avem nevoie mai întâi de numele lunii și de numărul de zile din ea. Soluția pare destul de simplă:

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 +
               '}';
   }
}
Întregul shabang! Avem o Monthclasă, câmpurile necesare, getter/setters și toString(). Dacă, desigur, nu trebuie să adăugăm equals()șihashCode()pentru a atinge fericirea deplină :) Dar aici avem o problemă conceptuală. După cum probabil vă amintiți, unul dintre principalele avantaje ale OOP este că face ușoară modelarea entităților din lumea reală. Un scaun, o mașină, o planetă — toate aceste concepte din viața obișnuită sunt ușor de reprezentat într-un program cu ajutorul abstracției. Problema este că unele entități din lumea reală au o gamă strict limitată de valori. Sunt doar 4 sezoane într-un an. Există doar 8 note într-o octavă. Calendarul are doar 12 luni. Și Danny Ocean de la Ocean's 11 are doar 11 prieteni (deși acest lucru nu contează :)) Ceea ce contează este că o clasă Java obișnuită nu este capabilă să modeleze aceste entități și să le impună limitările naturale. Al nostruMonthclasa are toate câmpurile obligatorii. Dar dacă un alt programator îl folosește, nimeni nu îl poate opri să creeze obiecte complet nebunești:

public class Main {

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

}
Dacă acest lucru apare în codul nostru, nu va fi ușor să găsiți vinovatul! Pe de o parte, programatorul care creează obiectele ar putea realiza că Monthclasa înseamnă „lună într-un an” și să nu scrie asemenea prostii. Pe de altă parte, programatorul profită doar de abilitățile oferite de designerul clasei. Este posibil să atribuiți nume și numere arbitrare de zile? Exact asta am primit. Atunci ce ar trebui să facem în această situație? Sincer, înainte de lansarea Java 1.5, programatorii trebuiau să fie creativi :) În acele vremuri, au creat structuri ca aceasta:

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 +
               '}';
   }
}
Aici am redus numărul de luni de la douăsprezece la trei pentru a scurta exemplul. Astfel de modele au făcut posibilă rezolvarea problemei. Capacitatea de a crea obiecte a fost limitată la un constructor privat:

private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }
Programatorii care folosesc clasa nu puteau să creeze pur și simplu Monthobiecte. Au trebuit să folosească obiectele statice finale furnizate de dezvoltatorul clasei. De exemplu, așa:

public class Main {

   public static void main(String[] args) {

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

}
Dar, dezvoltatorii Java au atras atenția asupra problemei existente. Desigur, este grozav că programatorii au reușit să vină cu o soluție folosind instrumentele disponibile în limbaj, dar nu pare foarte ușor! Era nevoie de o soluție evidentă, chiar și pentru începători. Și așa Enuma apărut în Java. Practic, Enumeste o clasă Java care oferă un set limitat de valori obiect. Iată cum arată:

public enum Month {
  
   JANUARY,
   FEBRUARY,
   MARCH
}
În definiție, am indicat că Enumeste o clasă Java, dar este cu adevărat adevărat? Da, și chiar putem verifica. De exemplu, încercați să faceți Monthenumerarea noastră să moștenească o altă clasă:

public abstract class AbstractMonth {
}

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

   JANUARY,
   FEBRUARY,
   MARCH
}
De ce se întâmplă asta? Când scriem:

public enum Month
compilatorul convertește această declarație în următorul cod:

public Class Month extends Enum
După cum știți deja, Java nu acceptă moștenirea multiplă. Prin urmare, nu putem moșteni AbstractMonth. EnumCum poate fi folosită această nouă construcție ? Și cum diferă de vechiul construct cu static finalcâmpuri? Ei bine, ca exemplu, vechiul construct nu ne permitea să folosim propriul nostru set de valori în switchdeclarații. Imaginați-vă că vrem să creăm un program care să ne amintească de sărbătorile sărbătorite în fiecare lună:

public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {

           // Error!
           case JANUARY:
       }
   }
}
După cum puteți vedea, compilatorul aruncă o eroare aici. Dar odată ce enuma apărut în Java 1.5, totul a devenit mult mai simplu:

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

   }

}
Ieșire din consolă:

New Year's Day is January 1st!
Rețineți că accesul la Enumobiecte a rămas static, așa cum era înainte de Java 1.5. Nu trebuie să creăm un Monthobiect pentru a accesa lunile. Când lucrați cu enumerari, este foarte important să nu uitați că Enumeste o clasă cu drepturi depline. Aceasta înseamnă că, dacă este necesar, puteți defini constructori și metode în el. De exemplu, în fragmentul de cod anterior, am specificat pur și simplu valorile: IANUARIE, FEBRUARIE, MARTIE. Cu toate acestea, ne putem extinde Monthenumerarea astfel:

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 +
               '}';
   }
}
Aici am dat enumcele 2 câmpuri ale noastre (numele lunii și numărul de zile), un constructor care folosește aceste câmpuri, getter/setters, metoda toString()și 2 metode statice. După cum puteți vedea, nu au fost probleme cu asta. Din nou, Enumîntr-adevăr este o clasă cu drepturi depline:

import java.util.Arrays;

public class Main {

   public static void main(String[] args) {

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

   }

}
Ieșire din consolă:

[Month{name='June', daysCount=30}, Month{name='July', daysCount=31}, Month{name='August', daysCount=31}]
În fine, vreau să recomand o carte Java extrem de utilă și anume „Effective Java” de Joshua Bloch . Enum.  Exemple practice.  Adăugarea de constructori și metode - 3Autorul este unul dintre creatorii Java, așa că puteți avea încredere în sfaturile sale despre cum să utilizați corect și competent instrumentele limbajului :) În ceea ce privește lecția noastră, vă recomand să acordați o atenție deosebită capitolului cărții despre Enum. Lectura placuta! :)
Comentarii
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION