Menu
Coddy logo textTech

Klasy i metody abstrakcyjne

Część sekcji Programowanie obiektowe ścieżki Java w Coddy. Lekcja 32 z 87.

Czasami chcesz zdefiniować klasę, która służy jako szablon, ale nigdy nie powinna być bezpośrednio instancjonowana. Na przykład ogólna klasa Shape ma sens jako klasa nadrzędna, ale jak miałby wyglądać „kształt” bez konkretnej formy? Właśnie w takich sytuacjach przydają się klasy abstrakcyjne.

Klasa abstrakcyjna jest deklarowana za pomocą słowa kluczowego abstract i nie można jej tworzyć jako instancji. Może zawierać zarówno zwykłe metody z implementacją, jak i metody abstrakcyjne, które nie mają treści:

public abstract class Shape {
    protected String color;
    
    public Shape(String color) {
        this.color = color;
    }
    
    // Metoda abstrakcyjna – bez implementacji
    public abstract double getArea();
    
    // Zwykła metoda – ma implementację
    public String getColor() {
        return color;
    }
}

Metody abstrakcyjne deklarują co podklasa musi robić, ale nie jak. Każda nieabstrakcyjna klasa rozszerzająca klasę abstrakcyjną musi dostarczyć implementacje wszystkich metod abstrakcyjnych:

public class Circle extends Shape {
    private double radius;
    
    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }
    
    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
}

Nadal możesz używać klas abstrakcyjnych jako typów referencyjnych, co umożliwia polimorfizm:

Shape shape = new Circle("red", 5.0);
System.out.println(shape.getArea());  // Wywołuje implementację klasy Circle

Klasy abstrakcyjne są idealne, gdy podklasy współdzielą wspólny kod, ale każda z nich musi implementować określone zachowania w inny sposób. Wymuszają przestrzeganie kontraktu, jednocześnie umożliwiając ponowne wykorzystanie kodu.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system urządzeń, który pokazuje możliwości klas abstrakcyjnych. Utworzysz bazową klasę Appliance, która określa, co musi robić każde urządzenie, pozostawiając konkretnym typom urządzeń decyzję, jak dokładnie to robią.

Rozmieścisz kod w czterech plikach:

  • Appliance.java: Utwórz klasę abstrakcyjną, która będzie wzorcem dla wszystkich urządzeń. Każde urządzenie ma pole brand (String) i pole wattage (int). Dodaj konstruktor inicjalizujący oba pola, metody pobierające wartość każdego z nich oraz zwykłą metodę getInfo(), która zwraca: [brand] - [wattage]W. Zdefiniuj metodę abstrakcyjną operate(), którą muszą implementować podklasy — określa ona, jak każde urządzenie wykonuje swoją główną funkcję.
  • WashingMachine.java: Utwórz konkretną klasę rozszerzającą Appliance. Pralki mają dodatkowe pole capacity (int), określające wielkość wsadu w kg. Użyj super, aby obsłużyć inicjalizację klasy nadrzędnej. Zaimplementuj metodę operate(), aby wyświetlała: [brand] washing machine is washing [capacity]kg of clothes
  • Microwave.java: Utwórz kolejną konkretną klasę rozszerzającą Appliance. Kuchenki mikrofalowe mają pole power (int), określające procentowy poziom mocy. Zaimplementuj metodę operate(), aby wyświetlała: [brand] microwave is heating at [power]% power
  • Main.java: Połącz wszystkie elementy, wykorzystując polimorfizm. Otrzymasz pięć danych wejściowych: nazwę marki, moc w watach, pojemność pralki, nazwę drugiej marki oraz poziom mocy kuchenki mikrofalowej. Utwórz obiekt WashingMachine i obiekt Microwave, a następnie przechowaj je w tablicy odwołań do Appliance. Przejdź pętlą przez tablicę i dla każdego urządzenia wyświetl jego informacje za pomocą getInfo(), a następnie wywołaj operate().

Otrzymasz pięć danych wejściowych w następującej kolejności: pierwsza marka (String), pierwsza moc w watach (int), pojemność w kg (int), druga marka (String) i poziom mocy (int).

Wynik powinien zawierać cztery wiersze — dla każdego urządzenia zobaczysz wiersz z jego informacjami, a następnie opis jego działania. Zwróć uwagę, jak klasa abstrakcyjna pozwala traktować różne urządzenia w jednolity sposób, podczas gdy każde z nich działa na swój własny sposób!

Spróbuj swoich sił

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Wczytaj dane wejściowe
        String brand1 = scanner.nextLine();
        int wattage1 = scanner.nextInt();
        int capacity = scanner.nextInt();
        scanner.nextLine(); // pomiń znak nowej linii
        String brand2 = scanner.nextLine();
        int power = scanner.nextInt();
        
        // TODO: Utwórz obiekt WashingMachine z brand1, wattage1 i capacity
        
        // TODO: Utwórz obiekt Microwave z brand2, wattage1 (lub odpowiednią mocą) i power
        
        // TODO: Utwórz tablicę referencji do Appliance i umieść w niej oba obiekty
        
        // TODO: Przejdź przez tablicę i dla każdego urządzenia:
        // - Wypisz jego informacje za pomocą getInfo()
        // - Wywołaj operate()
    }
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Java online