🐍Python🐍 zajęcia 10

🐍Python🐍 zajęcia 10
Photo by David Clode / Unsplash

  • klasy obiektów - podstawowe informacje, struktura, atrybuty i metody
  • dziedziczenie - podstawowe informacje, rodzaje dziedziczenia
  • nadpisywanie metody

Klasy obiektów

❗nie mylić: KLASA to nie jest ❌OBIEKT❌ !!

  • Klasa to „szablon” lub „przepis”, który opisuje, jak tworzyć obiekty — czyli konkretne egzemplarze tego szablonu.
          • np. to ogólny opis stereotypowego kota
  • Obiekt to pojedyncza realizacja, zawierająca konkretne dane i zachowania.
          • np. to opis rudego kota sąsiada (konkretny przypadek)
  • po co używamy klas?
    • klasy przydatne są, kiedy chcemy unikać powtórzeń
    • podejście obiektowe ułatwia pracę w zespole i dzielenie zadań w projekcie

❗Dobra praktyka ❗ - klasa powinna zaczynać się od dużej litery

  • podstawowe struktury:
    • class Nazwa: – definicja klasy, zwyczajowo nazwa z wielkiej litery.
    • __init__ to specjalna metoda , która ustawia początkowe wartości (atrybuty) obiektu.
    • self to odwołanie do samego obiektu

  • tworzenie klasy:
class Osoba:
    def __init__(self, imie, wiek):
        self.imie = imie
        self.wiek = wiek

    def przywitaj_sie(self):
        print(f"Cześć, mam na imię {self.imie} i mam {self.wiek} lat.")
  • tworzenie obiektu:
jan = Osoba("Jan", 30)
jan.przywitaj_sie()  # Wyświetli: Cześć, mam na imię Jan i mam 30 lat.

  • Atrybuty
    • Definicja: Zmienne przechowywane w obiekcie (lub klasie), które opisują jego stan lub cechy.
    • Rodzaje:
      • Atrybuty instancji – unikalne dla każdego obiektu, definiowane zwykle w __init__.
      • Atrybuty klasowe – wspólne dla wszystkich obiektów danej klasy.
class Samochod:
    # atrybut klasowy
    kategoria = "pojazd"
    
    def __init__(self, marka, kolor):
        self.marka = marka  # atrybut instancji
        self.kolor = kolor

auto1 = Samochod("Toyota", "czerwony")
auto2 = Samochod("Honda", "czarny")

print(auto1.marka)  # Toyota
print(auto2.kategoria)  # pojazd
  • Metody
    • Definicja: Funkcje zdefiniowane wewnątrz klasy, które opisują zachowanie obiektu.

Dziedziczenie

  • to mechanizm, dzięki któremu nowa klasa (podklasa) może przejmować atrybuty i metody z innej klasy (nadklasy), a następnie je rozszerzać lub modyfikować.
  • Dziedziczenie to sposób, by tworzyć nowe klasy bazując na starych, dodając lub zmieniając ich funkcjonalność, a przy tym nie powielać kodu.

Po co stosować dziedziczenie?

    • Unikamy powielania kodu (reusability).
    • Możemy tworzyć klasy ogólne, a potem wyspecjalizowane.
    • Ułatwia utrzymanie i rozwój kodu.
  • składnia:
class Zwierze:  # klasa bazowa (nadklasa)
    def __init__(self, imie):
        self.imie = imie

    def przedstaw_sie(self):
        print(f"Jestem zwierzęciem o imieniu {self.imie}.")

class Pies(Zwierze):  # klasa pochodna (podklasa)
    def szczekaj(self):
        print("Hau hau!")

# Użycie
pies = Pies("Burek")
pies.przedstaw_sie()  # odziedziczone z Zwierze
pies.szczekaj()       # metoda z Pies

nadpisywanie metody w podklasie - tworzenie metody o takiej samej nazwie jak w klasie bazowej, ale z inną treścią.

    • Dzięki nadpisywaniu można zmienić lub dopasować zachowanie odziedziczonej metody
    • podstawowa struktura nadpisywania:
class Pies(Zwierze):
    def przedstaw_sie(self):
        print(f"Jestem psem o imieniu {self.imie}.")
    • przykład nadpisywania - klasa Zwierzę ma metodę dźwięk, którą zmieniamy w podklasie Pies (gdyby było więcej cech Psa, pozostałyby one po tym nadpisaniu niezmienione) :
class Zwierze:
    def dzwiek(self):
        print("Jakieś zwierzę wydaje dźwięk.")

class Pies(Zwierze):
    def dzwiek(self):  # NADPISUJEMY metodę
        print("Hau hau!")

pies = Pies()
pies.dzwiek()  # wynik: Hau hau!

wywołanie metody z klasy bazowej - Jeśli chcesz zachować część zachowania z klasy bazowej ale dodać do niej jakąś funkcjonalność, używasz super():

class Pies(Zwierze):
    def __init__(self, imie, rasa):
        super().__init__(imie)  # wywołanie konstruktora z Zwierze
        self.rasa = rasa
    • przykład:
class Zwierze:
    def dzwiek(self):
        print("Wydaję jakiś dźwięk.")  # podstawowe zachowanie

class Pies(Zwierze):
    def dzwiek(self):
        super().dzwiek()  # zachowujemy zachowanie bazowe
        print("Hau hau!")  # dodajemy coś od siebie

pies = Pies()
pies.dzwiek()

wynik: Wydaję jakiś dźwięk.
Hau hau!

  • super() jest użyteczne, gdy:
    • chcesz rozszerzyć, a nie zastąpić działanie metody,
    • pracujesz z gotowym kodem, którego nie chcesz przepisywać,
    • musisz zachować część starej logiki (np. inicjalizację, logowanie, konfigurację).

Rodzaje dziedziczenia w Pythonie

  • Pojedyncze – jedna nadklasa.
  • Wielokrotne – klasa może dziedziczyć po wielu klasach.
  • Wielopoziomowe – klasa dziedziczy po klasie, która sama jest już podklasą innej.
  • Hierarchiczne – wiele podklas dziedziczy po jednej nadklasie.