﻿# Rozwiązanie zadania 3: Atrybut obliczany - pole prostokąta
# Używamy języka angielskiego w kodzie, ale polskich komentarzy.

class Rectangle:
    """
    Klasa reprezentująca figurę geometryczną - prostokąt.
    Pokazuje, jak wykorzystać @property do "atrybutów wyliczanych" (computed properties).
    Oblicza wartości na bieżąco, aby zawsze były spójne ze stanem obiektu.
    """

    def __init__(self, width, height):
        """
        Konstruktor prostokąta. Inicjalizuje dwa publiczne atrybuty.
        Zwróć uwagę, że nie ma tu zmiennej instancji 'self.area'.
        Gdybyśmy przechowywali pole jako zmienną, musielibyśmy o nim pamiętać za 
        każdym razem, kiedy zmieniamy np. 'width'. Dzięki @property ten problem znika.
        """
        self.width = width
        self.height = height

    @property
    def area(self):
        """
        Obliczane pole prostokąta. 
        Za każdym razem, gdy użytkownik odwoła się do 'prostokat.area',
        ta metoda zostanie wykonana by zwrócić najświeższy i pewny wynik.
        Dzięki temu nie ryzykujemy istnienia 'nieaktualnych' danych (stale data problem).
        """
        return self.width * self.height

# Blok testowy
if __name__ == '__main__':
    print("--- Utworzenie pierwszego prostokąta ---")
    rect = Rectangle(4, 5)
    
    # Kiedy wywołujemy 'rect.area', w tle natychmiast wylicza się: 4 * 5
    print(f"Szerokość: {rect.width}, Wysokość: {rect.height}")
    print(f"Obliczone pole: {rect.area}")

    print("\n--- Zmiana jednego wymiaru ---")
    rect.width = 10
    print("Zmieniliśmy szerokość z 4 na 10.")
    
    # Jak widać niżej, pole zostanie zaktualizowane natychmiastowo, z racji że 
    # to computed property. Gdyby to był zwykły atrybut self.area wyliczony w 
    # konstruktorze, poniższy print zwróciłby błędnie '20', a nie '50'.
    print(f"Nowe pole po zmianie: {rect.area}")
