Menu
Coddy logo textTech

Klasy i metody abstrakcyjne

Część sekcji Programowanie obiektowe ścieżki Python w Coddy. Lekcja 25 z 64.

Klasy abstrakcyjne to klasy, których nie można bezpośrednio utworzyć jako instancji i które zawierają metody abstrakcyjne, które muszą zostać zaimplementowane przez podklasy.

Wyobraź sobie formularz: Klasa abstrakcyjna przypomina obowiązkowy formularz, w którym niektóre pola są wymagane (metody abstrakcyjne), a inne opcjonalne (metody konkretne). Nie możesz wysłać samego formularza — najpierw musisz wypełnić wszystkie wymagane pola. Podobnie nie możesz utworzyć instancji klasy abstrakcyjnej, dopóki wszystkie metody abstrakcyjne nie zostaną zaimplementowane w podklasie.

Zaimportuj moduł abc, aby tworzyć klasy abstrakcyjne:

from abc import ABC, abstractmethod

Utwórz klasę abstrakcyjną z metodami abstrakcyjnymi:

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass
    
    @abstractmethod
    def perimeter(self):
        pass
    
    def describe(self):
        return "This is a shape"  # Metoda konkretna (ma implementację)

Dekorator @abstractmethod oznacza metody, które podklasy muszą zaimplementować — są to „wymagane pola” w formularzu. Zwykłe metody, takie jak describe(), mogą mieć implementacje i są dziedziczone bez zmian — są to „wstępnie wypełnione pola”.

Dlaczego używać klas abstrakcyjnych? Wymuszają one przestrzeganie kontraktu. Jeśli utworzysz klasę Shape, oznacza to, że „każdy kształt MUSI umieć obliczyć swoje pole i obwód”. Zapobiega to błędom, które mogą się pojawić, gdy zapomnisz zaimplementować kluczowe metody.

Spróbuj utworzyć instancję klasy abstrakcyjnej:

# To spowoduje błąd:
# shape = Shape()  # TypeError: Can't instantiate abstract class

Ten błąd jest zamierzony — to tak, jakby próbować wysłać pusty formularz. Python mówi: „Nie wypełniono jeszcze wymaganych pól (metod area i perimeter)!”

Utwórz konkretną podklasę, która implementuje wszystkie metody abstrakcyjne:

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14 * self.radius ** 2
    
    def perimeter(self):
        return 2 * 3.14 * self.radius

Teraz „wypełniliśmy wszystkie wymagane pola” — zaimplementowaliśmy zarówno area(), jak i perimeter(). Klasa Circle jest teraz kompletną, konkretną klasą, którą można utworzyć jako instancję.

Teraz możesz tworzyć instancje konkretnej klasy:

circle = Circle(5)
print(circle.area())
print(circle.perimeter())
print(circle.describe())  # Odziedziczona metoda konkretna

Utwórz kolejną konkretną klasę pochodną:

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width  self.height
    
    def perimeter(self):
        return 2 * (self.width + self.height)

rectangle = Rectangle(4, 6)
print(rectangle.area())
print(rectangle.perimeter())

Wynik:

78.5
31.400000000000002
This is a shape
24
20

Klasy abstrakcyjne definiują kontrakt, którego podklasy muszą przestrzegać. Użyj ABC i @abstractmethod, aby utworzyć klasy abstrakcyjne. Podklasy muszą implementować wszystkie metody abstrakcyjne, w przeciwnym razie same również będą abstrakcyjne. Zapewnia to spójność i zapobiega niekompletnym implementacjom.

challenge icon

Wyzwanie

Średni

W tym wyzwaniu zaimplementujesz system przetwarzania płatności.

Musisz dokończyć implementację w tych plikach:

  • paymentmethod.py — abstrakcyjna klasa bazowa z logiką walidacji
  • creditcard.py — implementacja płatności kartą kredytową
  • paypal.py — implementacja płatności PayPal

Postępuj zgodnie z komentarzami TODO w każdym pliku, aby zaimplementować wymagane funkcje. Komentarze poprowadzą Cię krok po kroku przez tworzenie metod abstrakcyjnych, implementowanie konkretnych podklas oraz ustanawianie prawidłowych zależności importu między plikami.

Plik driver.py zawiera przypadki testowe, które sprawdzą, czy Twoja implementacja działa poprawnie, obsługując różne scenariusze płatności i wyświetlając odpowiednie szczegóły dla każdej metody płatności.

Spróbuj swoich sił

from creditcard import CreditCard
from paypal import PayPal

# Przetestuj implementacje - NIE MODYFIKUJ TEGO KODU TESTOWEGO
cc = CreditCard("1234567890123456")
pp = PayPal("user@example.com")

# Przetwórz poprawne płatności
if cc.validate(100):
    print(cc.process_payment(100))
    print(cc.payment_details())

if pp.validate(200):
    print(pp.process_payment(200))
    print(pp.payment_details())

# Wypróbuj nieprawidłową kwotę
if not pp.validate(0):
    print("Invalid payment amount")

# Po usunięciu znacznika komentarza wystąpiłby błąd:
# pm = PaymentMethod()  # Nie można utworzyć instancji klasy abstrakcyjnej
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 Python online