JAVA

Sanghera 69 - 73






Heller ! 195-200
Перерахування
вводить перерахування, який є класом з деякою додатковою функціональністю, а також певні обмеження. Перерахування є підкласами java.lang.Enum. Вони спрямовані на вирішення проблеми, яка найкраще пояснити на прикладі. Припустимо, що ви програмування Java на базі автоматичного автомобіля. Одним із завдань автомобіля буде реагувати на смугу зустрічного світлофора. Таким чином, ви вирішили створити клас TrafficLight для encap- sulate червоний / жовтий / зелений на статус світла. Ось один підхід:
Відкритий клас TrafficLight {
приватна INT стан; // 1 означає червоний
// 2 означає жовтий
// 3 означає зелений
суспільне INT GetState () {стан повернення;}
Припустимо, що клас також містить код синхронізації для зміни стану через певні проміжки часу.
Цей код не має значення тут.
 Цей клас надзвичайно схильний до помилок. Той, хто змінює клас або викликає GetState () повинен знати, що означає 1 червоний, 2 означає жовтий, а 3 означає зелений. Якщо хто-код отримує кон- злиті навіть на мить про те, яке значення означає, який колір, отриманий в результаті помилка може бути дуже важко відстежити.
Загальне рішення ввести константи:
Відкритий клас TrafficLight {
громадські остаточні статичні INT RED = 1; громадські остаточні статичні INT YELLOW = 2; громадські остаточні статичні INT ЗЕЛЕНИЙ = 3;
приватна INT стан; суспільне INT GetState () {
повертати стан;
Це трохи краще. Справді, до версії 5.0 це був найкращий з можливих підходів короткої записи про сторінку стомлюючого коду підтримки. Проте, ця версія TrafficLight все ще є проблеми. Можна сподіватися, що всі, хто називає GetState () буде розглядати повертається значення відповідним чином, як це:

Перемикач (nextTrafficLight.getState ()) {випадок TrafficLight.RED:
СТОП(); перерва;
випадок TrafficLight.YELLOW: floorIt ();
перерва;
випадок TrafficLight.GREEN: перейти ();
перерва; за замовчуванням:
стверджують помилкові: "Дивний-кольорове світло";}
Цей код порівнює стан світлового сигналу тільки констант, визначених в класі TrafficLight,
ніколи не буквальну цілочисельних значень. Ви можете сподіваюся, що люди, які називають GetState () використовують цей підхід; ви можете наполягати, що вони роблять це в щоденній електронної пошти заміток; але ви не можете гарантувати, що вони будуть робити це.
Наш код до сих пір має безліч недоліків, особливо тих з них:
■ Можна призначити в межах дії значення сформулювати світла.
■ Друк стану світового є не дуже інформативним.
Більш надійний підхід показаний тут:

1. Відкритий клас LightState {
2. захищений остаточна назва String; 3.
4. громадськості остаточний статичний LightState RED = новий LightState ( "червоний");
5. громадськості остаточний статичний LightState жовтий = новий LightState ( "жовтий");
6. громадськості остаточний статичний LightState ЗЕЛЕНИЙ = новий LightState ( "зелений"); 7.
8. приватна LightState (String s) {
9. Ім'я = s;
10.} 11.
12. Назва громадського String () {
Назва 13. Повернення;
14.}
15.}

Новий підхід являє собою стану, використовуючи приклади з LightState класу, а не Інтс. Зверніть увагу, що конструктор є приватним, так що ви ніколи не можете побудувати всі екземпляри з поза класом або його підкласів; єдині екземпляри ви коли-небудь знадобиться побудовані статично. Ви не можете використовувати новий клас як аргумент перемикач заяву, як ви могли б з Інтс попереднього прикладу, але це невелика ціна, щоб заплатити. Наш вихідний код перемикання стає

LightState стан = nextTrafficLight.getState (); якщо (стан == LightState.RED)
СТОП();
інакше якщо (стан == LightState.YELLOW) floorIt ();
інакше якщо (стан == LightState.GREEN) продовжити ();
ще
стверджувати, помилково: "нульовий світло стан.";
Така конструкція гарантує, що тільки можливо, несподіваного значення стану для світлофора дорівнює нулю. Крім того, налагодження коду може роздрукувати будь LightState екземпляр і виробляти інформативний результат. Насправді, такий підхід є настільки корисним, що він має назву: типизированного перерахування шаблону дизайну. Вважається типизированного, тому що є спеціальний тип, єдиною метою яких є кодувати кілька перераховуються станів, що дозволяє уникнути небезпеки використання довільно задані значення Int. (Довільно призначені Інтс або інші примітиви знає як перераховуються константи.) У деяких мовах програмування (Pascal, наприклад) мають вбудовану підтримку для типизированного merations пере- чисельні. Java не зробив, до 1,5.
Існує тільки один недолік шаблону типизированного перерахування: вона вимагає багато кодування. Клас LightState показано вище, досить легко створити, але велика програма з великою кількістю формалізованих станів може зажадати десятки класів перерахування, і навіть досвідчені розробники могли б спробувати зрізати кути.
Java 5.0 підтримують перерахування типизированного забезпечує всі переваги класу LightState з дуже невеликим зусиллям програмування. Подібність між традиційними класами і перерахуваннями включають в себе наступне:
■ Ви можете оголосити перерахування в будь-якому місці ви можете оголосити клас.
■ Компіляція перерахування генерує .class файл, ім'я якого походить від імені ENUM в.
■ Переліки успадковують дані і методи від Object.
■ Перерахування можуть бути перетворені і кинь у відповідності з тими ж правилами, які регулюють будь-який клас, який розширює об'єкт.
■ Переліки можуть мати основні () методи і може бути використано в якості додатків.
■ Переліки, які не мають явних конструкторів отримати не за замовчуванням без ARGS конструкторів.
Перерахування мають обмежені функціональні можливості. Вони на відміну від традиційних класів, наступними способами:
■ Переліки оголошуються за допомогою ключового слова перерахувань, а не клас ключового слова.
Переліки не може бути реалізований.
■ Перерахування бути недоступними для нічого і не може бути продовжений.
■ перерахувань можуть бути аргументи в звітності комутатора.
■ Переліки мають вбудовані назви () і ToString () методи, обидва з яких повертає ім'я поточного екземпляра.
Перше твердження перерахування має спеціальний формат, як показано нижче. ось LightState
переписати у вигляді перерахування:

публічне перерахування LightState {червоний, жовтий, зелений;
}

Зверніть увагу на перший (і єдиний) оператор, який являє собою розділений комами список ідентифікаторів, закінчуватися крапкою з комою. Коли перерахування класу завантажений, один екземпляр створюється для кожного ідентифікатора в списку; ви можете думати про ідентифікаторів у який спосіб примірників. Імена стають публічними статичні кінцеві члени перерахування, так що ви можете послатися на випадки, як, наприклад, LightState.YELLOW. Примірники називаються константи перерахування в.
Наведений нижче код показує, як використовувати LightState ENUM. Припустимо, що GetState ()
Тепер метод повертає LightState, а не INT:

Перемикач (nextTrafficLight.getState ()) {випадок LightState.RED:
СТОП(); перерва;



випадок LightState.YELLOW: floorIt ();
перерва;
випадок LightState.GREEN: перейти ();
перерва; за замовчуванням:
стверджувати, помилково: "нульовий світло стан";
Цей код практично ідентичний оригінальній версії. Основна відмінність полягає в тому, що червоний, жовтий,
і ЗЕЛЕНИЙ тепер визначені в LightState, а не в TrafficLight. Це більш місце це доцільно для них. Єдина відмінність полягає в іншому виведене оператора Assert (оригінальна версія, надрукована "Strange-кольорове світло"). За допомогою перерахувань, світло не може мати дивний колір. Компілятор гарантує, що тільки екземпляри TrafficLight, які коли-небудь можуть існувати червоний, жовтий і зелений. Якщо значення, що повертається GetState () не є одним з цих значень, то воно повинно бути нульовим.
Часто простий перерахування, що містить тільки список імен все, що вам потрібно. Тим не менш, ви можете додати дані, методи і конструктори перерахування. Ось приклад, який додає все три. Припустимо, що ви хочете створити перерахування для подання костюми колоди карт. Ви могли б почати так:

публічне перерахування костюм {
КЛУБ, АЛМАЗ, СЕРЦЕ, SPADE;
}

Це нормально, поки ви не зрозумієте, що костюми пофарбовані, і підходить для костюма, щоб знати свій власний колір. Ось версія костюм, який підтримує кольору:
1.   enum Suit {
2.     DIAMOND(true), HEART(true), CLUB(false), SPADE(false); 3.
4. private boolean red; 5.
6.     Suit(boolean b) {
7.         red  = b;
8.  }
9.
10.     public boolean isRed() {
11.         return red;
12. } 13.
14.     public String toString() {
15.         String  s  = name();
14.     s +=  red ?
15.       ":red"   : ":black";
16.         return s;
18. }
19.}
Список імен в рядку 2 повинні з'являтися перед усіма іншими елементами перерахування. Рядок 4 являє собою звичайну декларацію даних. Рядки 6-8 представляють собою звичайний конструктор і ліній 10-12 є звичайним методом збруя. Ви очікували б побачити такий код в будь-якому класі з приватної логічної змінної називається червоним.
У Булев в круглі дужки в рядку 2 (після кожної назви) є аргументами конструктора. Якщо немає списку аргументів наступне ім'я екземпляра, цей екземпляр побудований з використанням НЕ-арг конструктор ENUM в. (Як і з традиційними класами, перерахування, без явного конструктора не отримує за замовчуванням без ARGS конструктор.) Проте, якщо ім'я екземпляра слід список аргументів, повинен бути конструктор з сумісним списком АГД. У нашому прикладі, конструктор в рядках 6-8 сумісний.
Рядок імені 16 викликів (), який представляє собою останній метод успадкований від java.lang.Enum. Метод ім'я () повертає ім'я даних примірника, як він з'являється в списку імен примірника. ToString () також повертає ім'я екземпляра, але не є остаточним. Так що ваші перерахувань можуть мати найвищий пріоритет ToString (), щоб надати додаткову інформацію, спираючись на заклик до імені ().
Як ви можете бачити, перерахувань дуже проста у використанні, завдяки функціональності, що надаються компілятором і успадкованих від суперкласу java.lang.Enum. Якщо ви отримуєте в звичку використовувати перерахувань замість перерахованих констант у всіх відповідних ситуаціях, ви будете шкодувати себе незліченні налагодження головні болі.





Немає коментарів:

Дописати коментар