Dziedziczenie i interfejsy w Javie w prosty sposób
Zaktualizowano 22 października 2026
Dziedziczenie i interfejsy w Javie opierają się na klasach i obiektach i oszczędzają ci pisania tego samego kodu dwa razy. Apartament to pokój hotelowy, tylko droższy. Zamiast pisać wszystko od nowa, dziedziczy po pokoju i zmienia tylko to, co jest inne. Interfejsy idą o krok dalej: określają tylko, co klasa musi umieć, a nie jak. Jedno i drugie pozwala pisać kod, który tak samo obsługuje wiele różnych klas.
Dziedziczenie przez extends
class Suite extends Room oznacza: apartament ma wszystkie pola i metody klasy Room. Room to nadklasa, a Suite to podklasa.
- Konstruktor podklasy w pierwszej linii wywołuje konstruktor nadklasy przez
super(...). - Metodę nadklasy możesz nadpisać: ta sama nazwa, te same parametry, nowe ciało.
@Overridenad nią sprawia, że kompilator sprawdza, czy taka metoda naprawdę istnieje w nadklasie. super.price()wywołuje wersję z nadklasy. W ten sposób ją rozszerzasz, zamiast kopiować wzór.- Podklasa nie widzi bezpośrednio pól
privatenadklasy. Korzysta z getterów, takich jakgetNights().
Zmienna typu Room może też przechowywać obiekt Suite. O tym, która metoda price() się wykona, decyduje obiekt, a nie typ zmiennej. Dlatego describe() liczy dla apartamentu wyższą cenę, chociaż describe() jest zapisane tylko w Room. Nazywa się to polimorfizmem.
class Room { private final int nights;
public Room(int nights) { this.nights = nights; }
public int getNights() { return nights; }
public double price() { return 80.0 * nights; }
public String describe() { return nights + " nights: " + price() + " €"; }}
class Suite extends Room { public Suite(int nights) { super(nights); }
@Override public double price() { return super.price() + 50.0 * getNights(); }}
public class Main { public static void main(String[] args) { Room room = new Room(2); Room suite = new Suite(2); System.out.println(room.describe()); System.out.println(suite.describe()); }}Klasy abstrakcyjne i interfejsy
Klasa abstrakcyjna (abstract class Vehicle) jest pomyślana tylko jako nadklasa. Nie możesz utworzyć obiektu bezpośrednio z niej. Metoda abstrakcyjna nie ma ciała, tylko nagłówek ze średnikiem. Każda podklasa musi ją zaimplementować, inaczej się nie skompiluje.
Interfejs zawiera tylko nagłówki metod: to umowa. Klasa spełnia ją przez implements i pisze wszystkie metody. Klasa może dziedziczyć tylko po jednej nadklasie, ale implementować dowolnie wiele interfejsów: class Lamp implements Switchable, Dimmable.
Metody i listy (zobacz listy i mapy w Javie), które znają tylko ogólny typ (List<Vehicle>, PaymentMethod method), działają z każdą podklasą. Czy obiekt dodatkowo implementuje interfejs, sprawdza instanceof: if (v instanceof Electric e) od razu daje ci obiekt jako e.
import java.util.ArrayList;import java.util.List;
abstract class Vehicle { private final String name;
public Vehicle(String name) { this.name = name; }
public abstract int wheels();
public String describe() { return name + " has " + wheels() + " wheels"; }}
interface Electric { int range();}
class Bicycle extends Vehicle { public Bicycle() { super("Bicycle"); }
@Override public int wheels() { return 2; }}
class ElectricCar extends Vehicle implements Electric { public ElectricCar() { super("Electric car"); }
@Override public int wheels() { return 4; }
@Override public int range() { return 400; }}
public class Main { public static void main(String[] args) { List<Vehicle> fleet = new ArrayList<>(); fleet.add(new Bicycle()); fleet.add(new ElectricCar()); for (Vehicle v : fleet) { System.out.println(v.describe()); if (v instanceof Electric e) { System.out.println(" range: " + e.range() + " km"); } } }}Sortowanie z Comparable
Collections.sort(list) sortuje listę, jeśli jej elementy są Comparable. Liczby i teksty już takie są, a własne klasy implementują w tym celu Comparable<Runner>. Jedyna metoda tego interfejsu, compareTo(other), zwraca:
- liczbę ujemną, jeśli
thisjest przedother, - liczbę dodatnią, jeśli jest po nim,
0, jeśli oba są równe.
Integer.compare(a, b) zwraca dokładnie to dla dwóch liczb. Dla kolejności malejącej zamieniasz argumenty miejscami. Przy remisie porównujesz potem drugą cechę, na przykład imię przez name.compareTo(other.name). Jak algorytm sortowania działa od środka, wyjaśnia artykuł o szybkich algorytmach sortowania.
import java.util.ArrayList;import java.util.Collections;import java.util.List;
class Runner implements Comparable<Runner> { private final String name; private final int seconds;
public Runner(String name, int seconds) { this.name = name; this.seconds = seconds; }
@Override public int compareTo(Runner other) { return Integer.compare(seconds, other.seconds); }
@Override public String toString() { return name + " (" + seconds + " s)"; }}
public class Main { public static void main(String[] args) { List<Runner> runners = new ArrayList<>(); runners.add(new Runner("Mia", 52)); runners.add(new Runner("Leo", 48)); runners.add(new Runner("Ana", 55)); Collections.sort(runners); System.out.println(runners);
System.out.println("Ada".compareTo("Bob")); System.out.println("Bob".compareTo("Ada")); System.out.println("Ada".compareTo("Ada")); }}Typowe błędy
Brak super(...)
Jeśli nadklasa ma tylko konstruktor z parametrami, każda podklasa musi go wywołać przez
super(...), i to w pierwszej linii. Inaczej kompilator zgłaszaconstructor Room in class Room cannot be applied to given types.Nadpisywanie bez @Override
Literówka w rodzaju
public double prize()albo inny typ parametru po cichu tworzy nową metodę, która nigdy nie zostanie wywołana. Z@Overridekompilator od razu zgłosi błąd.Ponowne deklarowanie pola w podklasie
Jeśli podklasa deklaruje pole o tej samej nazwie co nadklasa, obiekt ma potem dwa takie pola. Metody nadklasy widzą tylko swoje:
class Suite extends Room { private int nights; // hides Room's nights, stays 0}Pola należą tylko do klasy, która je wprowadza.
Obiekt klasy abstrakcyjnej
Kompilator odrzuca
new Vehicle("Bus")z komunikatemVehicle is abstract; cannot be instantiated. Utwórz obiekt podklasy; możesz go spokojnie zapisać w zmiennej typuVehicle.
Zadania z tego tematu
Przećwicz to, czego się nauczyłeś, od razu w przeglądarce. Testy natychmiast sprawdzają twoje rozwiązanie.
Powiązane artykuły
- Klasy i obiektyKlasy i obiekty w Javie w prosty sposób: pola, konstruktor, gettery, static i rekordy z przykładami. Do tego typowe błędy, np. przesłonięte pola.Czytaj artykuł
- Wyjątki i enumyWyjątki w Javie w prosty sposób: try, catch, finally, throw, własne wyjątki i enumy z przykładami. Do tego typowe błędy, np. puste bloki catch.Czytaj artykuł
- Lambdy i strumienieLambdy i strumienie w Javie w prosty sposób: filter, map, reduce, Comparator i groupingBy z przykładami. Do tego typowe błędy z toList() i reversed().Czytaj artykuł