Metody abstrakcyjne w enumach
Zachowanie poszczególnych stałych
Metody abstrakcyjne w enumach to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.
Zachowanie poszczególnych stałych
Czasami każda stała enuma potrzebuje innego zachowania, a nie tylko innych danych.
Java pozwala zadeklarować w enumie metodę abstrakcyjną i nadpisać ją dla każdej stałej. Jest to wzorzec implementowania metod specyficznych dla poszczególnych stałych.
public class Main {
enum Operation {
PLUS { public int apply(int a, int b) { return a + b; } },
MINUS { public int apply(int a, int b) { return a - b; } };
public abstract int apply(int a, int b);
}
public static void main(String[] args) {
System.out.println(Operation.PLUS.apply(3, 4));
System.out.println(Operation.MINUS.apply(10, 6));
}
}Jak to działa
Każda stała z własnym ciałem staje się anonimową podklasą enuma.
Metoda abstrakcyjna wymusza dostarczenie implementacji przez każdą stałą, dzięki czemu kompilator gwarantuje kompletność.
public class Main {
enum Operation {
TIMES { public int apply(int a, int b) { return a * b; } };
public abstract int apply(int a, int b);
}
public static void main(String[] args) {
// The constant is an instance of a generated subclass
System.out.println(Operation.TIMES.getClass().getSimpleName().isEmpty()
? "anonymous subclass" : Operation.TIMES.apply(6, 7));
}
}Pełny kalkulator
Cztery działania arytmetyczne występują jako stałe, a każda z nich ma własną implementację apply.
public class Main {
enum Operation {
PLUS { public double apply(double a, double b) { return a + b; } },
MINUS { public double apply(double a, double b) { return a - b; } },
TIMES { public double apply(double a, double b) { return a * b; } },
DIVIDE{ public double apply(double a, double b) { return a / b; } };
public abstract double apply(double a, double b);
}
public static void main(String[] args) {
double x = 6, y = 3;
for (Operation op : Operation.values()) {
System.out.printf("%s -> %.1f%n", op, op.apply(x, y));
}
}
}Łączenie pól i zachowania
Można połączyć pole (symbol) z zachowaniem właściwym dla poszczególnych stałych. Pole opisuje działanie, a metoda je wykonuje.
public class Main {
enum Operation {
PLUS("+") { public double apply(double a, double b) { return a + b; } },
MINUS("-") { public double apply(double a, double b) { return a - b; } };
private final String symbol;
Operation(String symbol) { this.symbol = symbol; }
public abstract double apply(double a, double b);
@Override public String toString() { return symbol; }
}
public static void main(String[] args) {
Operation op = Operation.PLUS;
System.out.println("2 " + op + " 3 = " + op.apply(2, 3));
}
}Dlaczego nie użyć switch
Można zaimplementować apply za pomocą pojedynczego switch na stałej, ale podejście z metodą abstrakcyjną jest bezpieczniejsze.
Jeśli później doda się stałą, kompilator wymusi dostarczenie dla niej ciała metody. Instrukcja switch mogłaby po cichu pominąć nowy przypadek.
public class Main {
enum Op {
SQUARE { public int apply(int n) { return n * n; } },
CUBE { public int apply(int n) { return n * n * n; } };
public abstract int apply(int n);
}
public static void main(String[] args) {
System.out.println(Op.SQUARE.apply(5));
System.out.println(Op.CUBE.apply(3));
}
}Metody konkretne obok abstrakcyjnych
Enum może łączyć metody abstrakcyjne i konkretne. Wspólną logikę należy umieścić w metodzie konkretnej, a zmienną logikę pozostawić abstrakcyjną.
public class Main {
enum Shape {
CIRCLE { public double area(double x) { return Math.PI * x * x; } },
SQUARE { public double area(double x) { return x * x; } };
public abstract double area(double x);
public String report(double x) { return this + " area = " + area(x); }
}
public static void main(String[] args) {
System.out.println(Shape.CIRCLE.report(2));
}
}Enumy strategii
Udoskonaleniem tego podejścia jest enum strategii: stałe delegują obsługę do zagnieżdżonego enuma strategii zamiast bezpośrednio nadpisywać metody.
Jest to przydatne, gdy kilka stałych współdzieli to samo zachowanie. W tym przykładzie dni robocze i weekendy różnią się sposobem obliczania wynagrodzenia.
public class Main {
enum PayType {
WEEKDAY { int overtime(int mins) { return mins; } },
WEEKEND { int overtime(int mins) { return mins * 2; } };
abstract int overtime(int mins);
int pay(int mins) { return mins + overtime(Math.max(0, mins - 480)); }
}
public static void main(String[] args) {
System.out.println("Weekend pay: " + PayType.WEEKEND.pay(540));
}
}Enum z interfejsem i ciałami stałych
Połączenie interfejsu z ciałami właściwymi dla poszczególnych stałych zapewnia maksymalną polimorficzność.
public class Main {
interface Command { String run(); }
enum Action implements Command {
START { public String run() { return "starting..."; } },
STOP { public String run() { return "stopping..."; } };
}
public static void main(String[] args) {
for (Action a : Action.values()) System.out.println(a.run());
}
}Dostęp do pól z poziomu ciał
Ciało właściwe dla stałej może odczytywać własne pola tej stałej, ponieważ każde ciało działa w kontekście danej instancji.
public class Main {
enum Tax {
STANDARD(0.20) { double apply(double amt) { return amt * (1 + rate); } },
REDUCED(0.05) { double apply(double amt) { return amt * (1 + rate); } };
protected final double rate;
Tax(double rate) { this.rate = rate; }
abstract double apply(double amt);
}
public static void main(String[] args) {
System.out.printf("%.2f%n", Tax.STANDARD.apply(100));
}
}Domyślnie, a potem nadpisanie
Można zdefiniować konkretne zachowanie domyślne w ciele enuma i nadpisać je tylko dla tych stałych, które się różnią.
public class Main {
enum Notifier {
EMAIL,
SMS { String send(String m) { return "SMS: " + m; } };
String send(String m) { return "EMAIL: " + m; }
}
public static void main(String[] args) {
System.out.println(Notifier.EMAIL.send("hi"));
System.out.println(Notifier.SMS.send("hi"));
}
}Miniaturowa maszyna stanów
Zachowanie właściwe dla poszczególnych stałych doskonale sprawdza się w maszynach stanów: każdy stan zna własne przejście.
public class Main {
enum State {
IDLE { State next() { return RUNNING; } },
RUNNING { State next() { return DONE; } },
DONE { State next() { return DONE; } };
abstract State next();
}
public static void main(String[] args) {
State s = State.IDLE;
for (int i = 0; i < 3; i++) { System.out.println(s); s = s.next(); }
System.out.println(s);
}
}Szybkie sprawdzenie
Proszę sprawdzić swoją wiedzę na temat abstrakcyjnych metod enumów.
Podsumowanie
Dowiedzieli się Państwo, jak definiować zachowanie poszczególnych stałych:
- Należy zadeklarować metodę abstrakcyjną i nadpisać ją w ciele każdej stałej.
- Każda stała staje się anonimową podklasą.
- Kompilator wymusza kompletność implementacji, co jest bezpieczniejsze niż switch.
- Pola, konkretne zachowanie domyślne i interfejsy można łączyć, tworząc rozbudowane enumy.
W następnej części: wydajny EnumSet.
public class Main {
enum E { A { int v() { return 1; } }; abstract int v(); }
public static void main(String[] args) {
System.out.println("Abstract enum recap: " + E.A.v());
}
}Często zadawane pytania
Czy lekcja „Metody abstrakcyjne w enumach” jest bezpłatna?
Tak — pełny tekst „Metody abstrakcyjne w enumach” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Metody abstrakcyjne w enumach”?
Zachowanie poszczególnych stałych Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Java Academy?
Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Metody abstrakcyjne w enumach”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?
Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Enummy z polami i metodami
- Metody abstrakcyjne w enumach
- EnumSet
- EnumMap