مقدمة في OOP — البرمجة الكائنية
مقدمة في البرمجة الكائنية (OOP)
حتى الآن نظمت برامجك بالدوال، والبيانات منفصلة عنها في قوائم وقواميس. هذا يعمل جيداً للبرامج الصغيرة. لكن عندما يكبر البرنامج تظهر مشكلة: دالة withdraw(account, amount) يمكن أن تُستدعى على أي قاموس، وأي جزء من الكود يمكنه تغيير account["balance"] مباشرة إلى قيمة خاطئة.
البرمجة الكائنية تجمع البيانات والدوال التي تعمل عليها في وحدة واحدة تسمى كائناً.
الصنف والكائن
- الصنف (class): المخطط أو القالب. مثل تصميم سيارة.
- الكائن (object / instance): نسخة حقيقية من الصنف. مثل سيارة محددة لها لون ورقم.
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def bark(self):
return f"{self.name} ينبح!"
rex = Dog("ريكس", 3) # إنشاء كائن
print(rex.name) # خاصية
print(rex.bark()) # دالة (method)__init__ و self
- __init__ تُستدعى تلقائياً عند إنشاء الكائن، ومهمتها تهيئة خصائصه.
- self تشير إلى الكائن نفسه الذي تعمل عليه الدالة. عندما تكتب rex.bark() فإن Python تنفذ فعلياً Dog.bark(rex)، فيصبح self هو rex.
- كل دالة داخل الصنف تأخذ self كمعامل أول.
خصائص الكائن وخصائص الصنف
class Car:
wheels = 4 # خاصية صنف: مشتركة بين كل الكائنات
def __init__(self, brand):
self.brand = brand # خاصية كائن: لكل سيارة قيمتها__str__ للطباعة
بدون __str__، طباعة الكائن تعرض شيئاً مثل <__main__.Car object at 0x...>. عرّفها لتمثيل مقروء:
def __str__(self):
return f"سيارة {self.brand}"متى تستخدم الأصناف؟
عندما يكون لديك "شيء" له حالة (بيانات تتغير) وسلوك (عمليات عليها): حساب بنكي، لاعب في لعبة، طلب شراء. للعمليات البسيطة بلا حالة، الدوال العادية أبسط وأفضل.
خطأ شائع
نسيان self في تعريف الدالة: def bark(): ثم rex.bark() ← TypeError: takes 0 positional arguments but 1 was given، لأن Python تمرر الكائن تلقائياً.
تمرين
أنشئ صنف Rectangle بخاصيتي العرض والارتفاع، ودوال area() و perimeter() و __str__، وأنشئ منه كائنين واطبعهما.
# تعريف صنف
class Person:
# Constructor - يُستدعى عند إنشاء كائن
def __init__(self, name, age):
self.name = name # خاصية
self.age = age
# Method - دالة
def greet(self):
return f"مرحباً، أنا {self.name}"
def have_birthday(self):
self.age += 1
return f"عيد ميلاد سعيد! عمري الآن {self.age}"
# إنشاء كائنات
person1 = Person("أحمد", 25)
person2 = Person("محمد", 30)
print(person1.name) # أحمد
print(person1.greet()) # مرحباً، أنا أحمد
print(person1.have_birthday())
# صنف مع قيم افتراضية
class Car:
# Class attribute (مشترك بين كل الكائنات)
wheels = 4
def __init__(self, brand, model, year=2024):
# Instance attributes
self.brand = brand
self.model = model
self.year = year
self.speed = 0
def accelerate(self, amount):
self.speed += amount
return f"السرعة الآن: {self.speed} كم/س"
def brake(self):
self.speed = max(0, self.speed - 10)
return f"السرعة الآن: {self.speed} كم/س"
def __str__(self):
return f"{self.year} {self.brand} {self.model}"
car = Car("تويوتا", "كامري")
print(car) # 2024 تويوتا كامري
print(car.accelerate(50))
print(Car.wheels) # 4اختبر فهمك