مدیریت باغ وحش

اصلاح شده

2026-07-25

from abc import ABC, abstractmethod


# ---------------------------------------------------------
# بخش ۱ و ۳: تعریف کلاس پایه انتزاعی (Abstraction)
# ---------------------------------------------------------
class Animal(ABC):
    """کلاس پایه انتزاعی برای همه حیوانات باغ‌وحش"""

    total_animals = 0  # class attribute -> مشترک بین همه نمونه‌ها

    def __init__(self, name, age):
        self.name = name                 # public attribute
        self._age = age                  # protected attribute (قرارداد: فقط داخلی)
        self.__health = 100              # private attribute (کپسوله‌سازی)
        Animal.total_animals += 1        # هر بار ساخت شیء جدید، شمارنده رو زیاد می‌کنه

    # --- کپسوله‌سازی با property ---
    @property
    def health(self):
        """getter برای سلامت حیوان"""
        return self.__health

    @health.setter
    def health(self, value):
        """setter با اعتبارسنجی - جلوگیری از مقدار نامعتبر"""
        if not 0 <= value <= 100:
            raise ValueError("سلامت باید بین 0 تا 100 باشد")
        self.__health = value

    # --- متد انتزاعی: هر کلاس فرزند مجبوره پیاده‌سازی کنه ---
    @abstractmethod
    def make_sound(self):
        pass

    # --- متد کلاسی: کار با خود کلاس، نه یک نمونه خاص ---
    @classmethod
    def get_total_animals(cls):
        return cls.total_animals

    # --- متد استاتیک: فقط یک تابع کمکی مرتبط با کلاس ---
    @staticmethod
    def is_valid_age(age):
        return age > 0

    # --- متد ویژه (dunder): نمایش خوانا هنگام print ---
    def __str__(self):
        return f"{self.name} ({self.__class__.__name__}), سن: {self._age}, سلامت: {self.__health}"

    # --- متد ویژه: مقایسه دو حیوان بر اساس نام ---
    def __eq__(self, other):
        return self.name == other.name


# ---------------------------------------------------------
# بخش ۲: وراثت - هر کلاس فرزند، Animal رو گسترش می‌ده
# ---------------------------------------------------------
class Lion(Animal):
    def make_sound(self):
        print(f"{self.name} says: Roar!")


class Parrot(Animal):
    def __init__(self, name, age, can_talk=True):
        super().__init__(name, age)      # فراخوانی سازنده والد
        self.can_talk = can_talk

    def make_sound(self):
        if self.can_talk:
            print(f"{self.name} says: Hello!")
        else:
            print(f"{self.name} says: Squawk!")


class Elephant(Animal):
    def make_sound(self):
        print(f"{self.name} says: Pawoo!")


# ---------------------------------------------------------
# کلاسی که مجموعه‌ای از حیوانات رو نگه می‌داره
# نمایش __len__ و duck typing
# ---------------------------------------------------------
class Zoo:
    def __init__(self, name):
        self.name = name
        self.animals = []

    def add_animal(self, animal):
        self.animals.append(animal)

    def __len__(self):
        return len(self.animals)

    # --- چندشکلی: صدا زدن یک متد یکسان روی انواع مختلف حیوان ---
    def make_all_sounds(self):
        for animal in self.animals:
            animal.make_sound()   # هرکدوم رفتار خودشون رو دارن


# ---------------------------------------------------------
# اجرای برنامه (Demo)
# ---------------------------------------------------------
if __name__ == "__main__":

    zoo = Zoo("باغ‌وحش تهران")

    lion = Lion("Simba", 5)
    parrot = Parrot("Polly", 2, can_talk=True)
    elephant = Elephant("Dumbo", 8)

    zoo.add_animal(lion)
    zoo.add_animal(parrot)
    zoo.add_animal(elephant)

    print("--- نمایش اطلاعات همه حیوانات (dunder __str__) ---")
    for a in zoo.animals:
        print(a)

    print("\n--- چندشکلی: هر حیوان صدای خودش رو تولید می‌کنه ---")
    zoo.make_all_sounds()

    print("\n--- کپسوله‌سازی: تغییر سلامت با اعتبارسنجی ---")
    lion.health = 80
    print(f"سلامت {lion.name}: {lion.health}")
    try:
        lion.health = 150   # مقدار نامعتبر
    except ValueError as e:
        print("خطا:", e)

    print("\n--- تلاش برای دسترسی مستقیم به متغیر private ---")
    try:
        print(lion.__health)
    except AttributeError as e:
        print("خطا:", e)

    print("\n--- متد کلاسی: تعداد کل حیوانات ساخته‌شده ---")
    print("تعداد کل:", Animal.get_total_animals())
    print("طول باغ‌وحش (__len__):", len(zoo))

    print("\n--- متد استاتیک: بررسی معتبر بودن سن ---")
    print(Animal.is_valid_age(5))    # True
    print(Animal.is_valid_age(-3))   # False

    print("\n--- تلاش برای ساخت شیء از کلاس انتزاعی ---")
    try:
        a = Animal("X", 1)
    except TypeError as e:
        print("خطا:", e)

    print("\n--- مقایسه دو شیء (__eq__) ---")
    lion2 = Lion("Simba", 5)
    print(lion == lion2)   # True چون نام یکسانه

    print("\n--- Duck Typing: هر شیئی که make_sound() داشته باشه کار می‌کنه ---")
    class RobotAnimal:
        def __init__(self, name):
            self.name = name
        def make_sound(self):
            print(f"{self.name} says: Beep Boop!")

    zoo.add_animal(RobotAnimal("R2D2"))  # نه از Animal ارث می‌بره، نه انتزاعیه
    zoo.make_all_sounds()