Skip to content

🥕 Abstrakcyjne klasy nadrzędne

Są to klasy służące jako szablony, które definiują strukturę i wymuszone metody dla klas pochodnych, ale same nie mogą być inicjalizowane. Używają dekoratora @abstractmethod do oznaczenia metod, które muszą być zaimplementowane w klasach pochodnych.

Korzyści wynikające z wykorzystywania abstrakcyjnych klas nadrzędnych
  • Spójność - wymusza implementację określonych metod.
  • Reużywalność - pozwala dzielić metody między klasami.
  • Polimorfizm - umożliwia jednolite używanie różnych klas.
from abc import ABC, abstractmethod

class Zwierze(ABC):
    # Ta metoda jest abstrakcyjna,
    # wymagana jest jej implementacja w klasach pochodnych
    @abstractmethod
    def wydaj_dzwiek(self):
        pass

class Pies(Zwierze):
    def wydaj_dzwiek(self):
        return "Hau hau!"

class Kot(Zwierze):
    def wydaj_dzwiek(self):
        return "Miau miau!"

ABC vs. raise NotImplementedError

Zanim pojawiły się klasy ABC, metody wymuszane na klasach pochodnych pisano przez ręczne zgłaszanie wyjątku:

class Zwierze:
    def wydaj_dzwiek(self):
        raise NotImplementedError("Klasa pochodna musi zaimplementować tę metodę!")

Różnica jest istotna:

@abstractmethod (ABC) raise NotImplementedError
Kiedy wykrywa błąd Przy tworzeniu instancji klasy pochodnej Dopiero przy wywołaniu metody w czasie działania
Czy można stworzyć obiekt bez implementacji Nie - Python odmówi Tak - błąd pojawi się później
Czytelność intencji Wysoka Niższa
from abc import ABC, abstractmethod

class Zwierze(ABC):
    @abstractmethod
    def wydaj_dzwiek(self):
        pass

class Ryba(Zwierze):
    pass  # brak implementacji wydaj_dzwiek

r = Ryba()  # TypeError: Can't instantiate abstract class Ryba
            # without an implementation for abstract method 'wydaj_dzwiek'

Preferuj ABC - błąd zostaje wykryty jak najwcześniej, zanim obiekt trafi do reszty kodu.

Przykład

Ta sama implementacja klasy Employee, ale jako abstrakcyjna klasa nadrzędna:

from abc import ABC, abstractmethod

class Employee(ABC):
    def __init__(self, first_name, last_name, employee_id, salary):
        self.first_name = first_name
        self.last_name = last_name
        self.employee_id = employee_id
        self.salary = salary

    @abstractmethod
    def display_info(self):
        pass