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()