﻿# OOP_LAB_4_zad_02.py
"""
Rozwiązanie zadania 2: System kadrowy (Nadpisywanie metod i super())
"""

class Pracownik:
    """
    Klasa bazowa reprezentująca pracownika w systemie kadrowym.
    """
    def __init__(self, nazwisko: str, pensja: float):
        # Inicjalizacja podstawowych danych każdego pracownika
        self.nazwisko = nazwisko
        self.pensja = pensja

    def oblicz_wyplate(self) -> float:
        """
        Zwraca bazową pensję pracownika.
        Metoda przewidziana do potencjalnego nadpisania w klasach pochodnych.
        """
        return self.pensja


class Manager(Pracownik):
    """
    Klasa pochodna reprezentująca managera.
    Dziedziczy zachowania i atrybuty z klasy Pracownik.
    """
    def __init__(self, nazwisko: str, pensja: float, bonus: float):
        # Funkcja super() dba o prawidłowe zainicjowanie nazwiska i pensji
        # za pomocą konstruktora zdefiniowanego w klasie Pracownik.
        super().__init__(nazwisko, pensja)
        # Manager otrzymuje dodatkowy, specyficzny tylko dla niego atrybut - bonus motywacyjny.
        self.bonus = bonus

    def oblicz_wyplate(self) -> float:
        """
        Nadpisana (overridden) metoda obliczania wypłaty.
        Dostarcza specyficzną implementację dla managera, rozszerzając bazową logikę.
        """
        # Użycie super().oblicz_wyplate() pozwala na zachowanie i ewentualną zmianę 
        # logiki naliczania podstawy w przyszłości bez konieczności zmiany kodu Managera.
        baza = super().oblicz_wyplate()
        # Sumujemy podstawę oraz bonus.
        return baza + self.bonus


if __name__ == "__main__":
    print("--- System kadrowy ---")
    
    # Tworzenie obiektów dwóch różnych typów.
    p = Pracownik("Kowalski", 3000)
    m = Manager("Nowak", 3000, 1000)
    
    print(f"Wypłata bazowa (Pracownik {p.nazwisko}): {p.oblicz_wyplate()}")
    print(f"Wypłata bazowa + bonus (Manager {m.nazwisko}): {m.oblicz_wyplate()}")
    
    print("\n--- Prezentacja polimorfizmu ---")
    # Umieszczamy obiekty w jednej liście mimo różnicy typów.
    lista_kadrowa = [p, m]
    
    # W pętli traktujemy obiekty identycznie wywołując wspólną metodę.
    # Dzięki polimorfizmowi każdy obiekt reaguje po swojemu (wywołuje odpowiednią wersję metody).
    for osoba in lista_kadrowa:
        print(f"{osoba.nazwisko}: wypłata wynosi {osoba.oblicz_wyplate()}")
        
    # Eksperyment: czy 'bonus' jest dostępny dla zwykłego Pracownika?
    # Weryfikujemy to za pomocą bloku try/except:
    try:
        print(p.bonus)
    except AttributeError as e:
        print(f"\nOczekiwany błąd atrybutu (Zwykły pracownik nie posiada bonusu): {e}")
