۱۱
برنامهنویسی شیءگرا (OOP) 🏗️
یاد میگیریم چطور کد رو مثل دنیای واقعی مدل کنیم!
OOP چیه و چرا مهمه؟
برنامهنویسی شیءگرا یه روش فکر کردنه که کد رو مثل دنیای واقعی مدل میکنه:
🌟 مفاهیم کلیدی OOP
- کلاس (Class): قالب یا نقشه برای ساخت آبجکتها
- آبجکت (Object): نمونهای از کلاس که در حافظه ساخته میشه
- ویژگی (Attribute): خصوصیات آبجکت
- متد (Method): رفتارها و عملکردهای آبجکت
مثال ساده: کلاس ماشین
# تعریف کلاس
class Car:
# متد سازنده (Constructor)
def __init__(self, brand, model, year):
# ویژگیهای آبجکت
self.brand = brand
self.model = model
self.year = year
self.speed = 0
self.is_running = False
# متدهای کلاس
def start_engine(self):
self.is_running = True
print(f"{self.brand} {self.model} روشن شد! 🚗")
def accelerate(self, amount):
if self.is_running:
self.speed += amount
print(f"سرعت به {self.speed} کیلومتر رسید")
else:
print("ابتدا ماشین را روشن کنید!")
def stop(self):
self.speed = 0
self.is_running = False
print(f"{self.brand} {self.model} متوقف شد")
def get_info(self):
return f"{self.year} {self.brand} {self.model} - سرعت: {self.speed} کیلومتر"
# ساخت آبجکتها (نمونهسازی)
my_car = Car("تویوتا", "کمری", 2023)
your_car = Car("بنز", "C200", 2022)
# استفاده از متدها
print("=== ماشین من ===")
print(my_car.get_info())
my_car.start_engine()
my_car.accelerate(50)
my_car.accelerate(30)
print(my_car.get_info())
print("\n=== ماشین شما ===")
print(your_car.get_info())
your_car.accelerate(40) # بدون روشن کردن موتور
your_car.start_engine()
your_car.accelerate(60)
print(your_car.get_info())
کپسولهسازی (Encapsulation)
کپسولهسازی یعنی مخفی کردن جزئیات داخلی و کنترل دسترسی به دادهها:
Private و Protected Attributes
class BankAccount:
def __init__(self, account_number, initial_balance=0):
self.account_number = account_number # Public
self._balance = initial_balance # Protected (با _)
self.__pin = "1234" # Private (با __)
self.__transaction_history = [] # Private
# Getter برای دسترسی به موجودی
def get_balance(self):
return self._balance
# Setter برای تغییر موجودی با اعتبارسنجی
def deposit(self, amount):
if amount > 0:
self._balance += amount
self.__add_transaction(f"واریز {amount:,} تومان")
print(f"✅ {amount:,} تومان واریز شد")
return True
else:
print("❌ مبلغ باید مثبت باشد")
return False
def withdraw(self, amount, pin):
# بررسی رمز
if not self.__verify_pin(pin):
print("❌ رمز اشتباه است")
return False
# بررسی موجودی
if amount > self._balance:
print("❌ موجودی کافی نیست")
return False
if amount <= 0:
print("❌ مبلغ باید مثبت باشد")
return False
self._balance -= amount
self.__add_transaction(f"برداشت {amount:,} تومان")
print(f"✅ {amount:,} تومان برداشت شد")
return True
# متدهای Private
def __verify_pin(self, pin):
return pin == self.__pin
def __add_transaction(self, description):
from datetime import datetime
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.__transaction_history.append(f"[{timestamp}] {description}")
# متد برای نمایش تاریخچه (با رمز)
def get_transaction_history(self, pin):
if self.__verify_pin(pin):
return self.__transaction_history.copy()
else:
return "❌ رمز اشتباه است"
def change_pin(self, old_pin, new_pin):
if self.__verify_pin(old_pin):
if len(new_pin) == 4 and new_pin.isdigit():
self.__pin = new_pin
self.__add_transaction("تغییر رمز عبور")
print("✅ رمز با موفقیت تغییر کرد")
return True
else:
print("❌ رمز باید ۴ رقم باشد")
return False
else:
print("❌ رمز فعلی اشتباه است")
return False
def __str__(self):
return f"حساب {self.account_number} - موجودی: {self._balance:,} تومان"
# تست کلاس حساب بانکی
account = BankAccount("123456789", 1000000)
print("=== اطلاعات حساب ===")
print(account)
print(f"موجودی: {account.get_balance():,} تومان")
print("\n=== تراکنشها ===")
account.deposit(500000)
account.withdraw(200000, "1234")
account.withdraw(2000000, "1234") # موجودی کافی نیست
account.withdraw(100000, "0000") # رمز اشتباه
print("\n=== تغییر رمز ===")
account.change_pin("1234", "5678")
account.withdraw(300000, "5678")
print("\n=== تاریخچه تراکنشها ===")
history = account.get_transaction_history("5678")
for transaction in history:
print(transaction)
💡 نکات مهم:
- Public: قابل دسترسی از همه جا
- Protected (_): فقط در کلاس و زیرکلاسها
- Private (__): فقط در همان کلاس
وراثت (Inheritance)
وراثت به ما اجازه میده کلاسهای جدید رو بر اساس کلاسهای موجود بسازیم:
سلسله مراتب کلاسها
# کلاس پایه (Parent/Base Class)
class Animal:
def __init__(self, name, species):
self.name = name
self.species = species
self.energy = 100
def eat(self, food):
self.energy += 20
print(f"{self.name} {food} خورد و انرژیاش به {self.energy} رسید")
def sleep(self):
self.energy += 30
print(f"{self.name} خوابید و انرژیاش به {self.energy} رسید")
def make_sound(self):
print(f"{self.name} صدایی میکند")
def get_info(self):
return f"{self.name} ({self.species}) - انرژی: {self.energy}"
# کلاس فرزند (Child/Derived Class)
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name, "سگ") # فراخوانی سازنده کلاس پدر
self.breed = breed
self.loyalty = 100
# Override کردن متد
def make_sound(self):
print(f"{self.name} واق واق میکند! 🐕")
# متدهای جدید
def fetch(self, item):
if self.energy >= 20:
self.energy -= 20
self.loyalty += 10
print(f"{self.name} {item} رو آورد! وفاداری: {self.loyalty}")
else:
print(f"{self.name} خسته است و نمیتواند بازی کند")
def guard(self):
if self.energy >= 30:
self.energy -= 30
print(f"{self.name} در حال نگهبانی است! 🛡️")
else:
print(f"{self.name} برای نگهبانی انرژی کافی ندارد")
# Override کردن get_info
def get_info(self):
base_info = super().get_info()
return f"{base_info} - نژاد: {self.breed} - وفاداری: {self.loyalty}"
class Cat(Animal):
def __init__(self, name, color):
super().__init__(name, "گربه")
self.color = color
self.independence = 80
def make_sound(self):
print(f"{self.name} میو میو میکند! 🐱")
def climb(self):
if self.energy >= 25:
self.energy -= 25
print(f"{self.name} بالا رفت! 🌳")
else:
print(f"{self.name} برای بالا رفتن انرژی کافی ندارد")
def hunt(self, prey):
if self.energy >= 40:
self.energy -= 40
self.independence += 5
print(f"{self.name} {prey} رو شکار کرد! استقلال: {self.independence}")
else:
print(f"{self.name} برای شکار انرژی کافی ندارد")
def get_info(self):
base_info = super().get_info()
return f"{base_info} - رنگ: {self.color} - استقلال: {self.independence}"
# تست کلاسها
print("=== ساخت حیوانات ===")
dog = Dog("رکس", "ژرمن شپرد")
cat = Cat("میتسی", "سیاه")
animals = [dog, cat]
print("\n=== اطلاعات حیوانات ===")
for animal in animals:
print(animal.get_info())
print("\n=== صداهای حیوانات ===")
for animal in animals:
animal.make_sound()
print("\n=== فعالیتهای خاص ===")
dog.fetch("توپ")
dog.guard()
cat.climb()
cat.hunt("موش")
تمرین عملی: سیستم مدیریت دانشجو
یک سیستم مدیریت دانشجو بنویس که شامل این موارد باشه:
- کلاس پایه Person با ویژگیهای مشترک
- کلاسهای Student و Teacher که از Person ارثبری کنن
- کلاس Course برای مدیریت دروس
- امکان ثبتنام، حذف و نمرهدهی
سیستم مدیریت دانشجو
from datetime import datetime
from abc import ABC, abstractmethod
class Person(ABC):
def __init__(self, name, person_id, email, phone):
self.name = name
self.person_id = person_id
self.email = email
self.phone = phone
self.created_at = datetime.now()
@abstractmethod
def get_role(self):
pass
def get_info(self):
return f"{self.get_role()}: {self.name} (ID: {self.person_id})"
def __str__(self):
return self.get_info()
class Student(Person):
def __init__(self, name, student_id, email, phone, major):
super().__init__(name, student_id, email, phone)
self.major = major
self.enrolled_courses = {}
self.gpa = 0.0
def get_role(self):
return "دانشجو"
def enroll_course(self, course):
if course.course_id in self.enrolled_courses:
return False, "قبلاً در این درس ثبتنام کردهاید"
success, message = course.add_student(self)
if success:
self.enrolled_courses[course.course_id] = {
'course': course,
'grade': None,
'attendance': 0
}
return success, message
def set_grade(self, course_id, grade):
if course_id not in self.enrolled_courses:
return False, "در این درس ثبتنام نکردهاید"
if not (0 <= grade <= 20):
return False, "نمره باید بین ۰ تا ۲۰ باشد"
self.enrolled_courses[course_id]['grade'] = grade
return True, f"نمره {grade} ثبت شد"
class Teacher(Person):
def __init__(self, name, teacher_id, email, phone, department):
super().__init__(name, teacher_id, email, phone)
self.department = department
self.teaching_courses = []
def get_role(self):
return f"استاد - {self.department}"
def assign_course(self, course):
if course not in self.teaching_courses:
self.teaching_courses.append(course)
course.teacher = self
return True, f"درس {course.name} اختصاص یافت"
return False, "این درس قبلاً اختصاص یافته"
class Course:
def __init__(self, name, course_id, units, capacity):
self.name = name
self.course_id = course_id
self.units = units
self.capacity = capacity
self.enrolled_students = []
self.teacher = None
def add_student(self, student):
if len(self.enrolled_students) >= self.capacity:
return False, "ظرفیت تکمیل است"
self.enrolled_students.append(student)
return True, f"ثبتنام در {self.name} موفق بود"
# تست سیستم
teacher = Teacher("دکتر احمدی", "T001", "ahmadi@uni.ac.ir", "021-1234", "کامپیوتر")
course = Course("برنامهنویسی پایتون", "CS101", 3, 30)
student = Student("علی رضایی", "S001", "ali@student.ac.ir", "0912-1234", "کامپیوتر")
teacher.assign_course(course)
student.enroll_course(course)
student.set_grade("CS101", 18)
print(f"استاد: {teacher}")
print(f"دانشجو: {student}")
print(f"درس: {course.name} - ظرفیت: {len(course.enrolled_students)}/{course.capacity}")
چالش پیشرفته: فروشگاه آنلاین
یک سیستم فروشگاه آنلاین طراحی کن با این ویژگیها:
- کلاسهای مختلف محصول (کتاب، لباس، الکترونیک)
- سیستم سبد خرید و پرداخت
- مدیریت موجودی و تخفیف
- سیستم امتیازدهی مشتری
💡 این چالش رو خودت حل کن و بعد با راهحل مقایسه کن!
نکات برای حل:
- از Abstract Base Class برای Product استفاده کن
- هر نوع محصول ویژگیهای خاص خودش رو داشته باشه
- سیستم تخفیف رو با Strategy Pattern پیاده کن
- برای سبد خرید از Composition استفاده کن