البرمجة كائنية التوجه في بايثون ببساطة: الأصناف والكائنات
الأصناف والكائنات والخصائص والدوال الخاصة بالكائن، والتغليف والوراثة بأمثلة من الحياة، ومتى تستخدم البرمجة كائنية التوجه ومتى تكفيك الدوال البسيطة.
- 7 دقائق قراءة
عندما تكبر برامجك، ستلاحظ أن البيانات والدوال التي تتعامل معها بدأت تتشابك. لديك قاموس لكل طالب، ودوال تحسب متوسطه، وأخرى تضيف له درجة، وثالثة تطبع تقريره، وكلها متناثرة في الملف. البرمجة كائنية التوجه (Object-Oriented Programming) طريقة لتنظيم الكود تجمع البيانات والدوال التي تخصها في وحدة واحدة تسمى الكائن. قد يبدو المصطلح معقدًا، لكن الفكرة قريبة جدًا من طريقة تفكيرنا في العالم من حولنا. في هذا المقال نشرحها ببساطة وبأمثلة من الحياة، ونوضح متى تفيدك فعلًا ومتى تكفيك الدوال العادية.
ماذا ستتعلم في هذا المقال؟
- الفرق بين الصنف (Class) والكائن (Object) بمثال من الحياة.
- كيف تعرّف صنفًا في بايثون: الدالة
__init__، والخصائص، والدوال الخاصة بالكائن. - المفاهيم الأساسية: التغليف والوراثة وتعدد الأشكال.
- متى تستخدم البرمجة كائنية التوجه ومتى لا تحتاج إليها.
الصنف والكائن: القالب والنسخة
فكر في استمارة التسجيل في الأكاديمية. الاستمارة الفارغة تحدد الحقول المطلوبة: الاسم، والعمر، والكورس. هذه الاستمارة هي الصنف (Class): قالب يصف الشكل العام. وكل استمارة مملوءة لطالب حقيقي، مريم أو يوسف، هي كائن (Object): نسخة محددة من القالب لها قيمها الخاصة. تستطيع أن تنشئ من الصنف الواحد عددًا غير محدود من الكائنات، ولكل منها بياناته المستقلة.
ولكل كائن شيئان: خصائص (Attributes) تصف حالته، مثل اسم الطالب ودرجاته، ودوال خاصة به (Methods) تصف ما يمكنه فعله أو ما يمكن فعله به، مثل إضافة درجة أو حساب المتوسط.
أول صنف لك في بايثون
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
self.scores = []
def add_score(self, score):
self.scores.append(score)
def average(self):
if not self.scores:
return 0
return sum(self.scores) / len(self.scores)
mariam = Student("مريم", 14)
mariam.add_score(95)
mariam.add_score(88)
print(mariam.name, mariam.average())
ماذا يحدث هنا؟
class Student: نعرّف صنفًا جديدًا. العرف أن تبدأ أسماء الأصناف بحرف كبير.__init__: دالة خاصة تُنفذ تلقائيًا عند إنشاء كائن جديد، وتجهز خصائصه الأولى. تسمى أحيانًا «المُنشئ».self: تشير إلى الكائن نفسه. عندما تكتبself.name = nameفأنت تحفظ الاسم داخل هذا الكائن تحديدًا، لا في متغير عام.Student("مريم", 14): ننشئ كائنًا من الصنف. بايثون تستدعي__init__وتمرر القيم.mariam.add_score(95): نستدعي دالة خاصة بالكائن باستخدام النقطة.
لو أنشأنا كائنًا آخر، youssef = Student("يوسف", 15)، فستكون له قائمة درجات مستقلة تمامًا عن درجات مريم. هذه هي الفكرة الجوهرية: كل كائن يحمل بياناته معه.
يشرح كوري شيفر في الفيديو التالي الأصناف والكائنات خطوة بخطوة، وهو الجزء الأول من سلسلة كاملة عن الموضوع باللغة الإنجليزية:
اجعل الكائن يعرّف بنفسه: الدالة __str__
جرّب أن تكتب print(mariam)، ستظهر لك رسالة غامضة فيها اسم الصنف وعنوان في الذاكرة. لكي تظهر معلومات مفيدة، أضف إلى الصنف دالة خاصة اسمها __str__ تعيد نصًا يصف الكائن، مثل اسم الطالب ومتوسطه. عندها ستعرض print هذا النص تلقائيًا. هذه الدوال التي تبدأ وتنتهي بشرطتين سفليتين تسمى «الدوال السحرية»، وهي التي تتيح لكائناتك أن تتصرف مثل أنواع بايثون المدمجة: أن تُطبع، وأن تُقارن، وأن تُجمع.
المفاهيم الأساسية الثلاثة
1. التغليف (Encapsulation)
التغليف يعني أن يحمل الكائن بياناته والدوال التي تتعامل معها، وأن يتحكم في طريقة تعديلها. مثلًا، بدل أن يضيف أي جزء من البرنامج درجة مباشرة إلى القائمة، نجعل الإضافة تمر عبر add_score، ونضع فيها شرطًا يرفض الدرجات الأقل من صفر أو الأكبر من مئة. هكذا نحمي البيانات من القيم الخاطئة في مكان واحد. وفي بايثون يُستخدم العرف أن الخاصية التي يبدأ اسمها بشرطة سفلية، مثل _scores، مخصصة للاستخدام الداخلي.
2. الوراثة (Inheritance)
الوراثة تسمح لك بإنشاء صنف جديد يبني على صنف موجود. لنفترض أن لدينا صنف Person فيه الاسم والعمر ودالة للتعريف بالنفس. يمكننا إنشاء صنف Student يرث كل ذلك ويضيف الدرجات، وصنف Teacher يرث الشيء نفسه ويضيف المادة التي يدرسها. هذا يمنع تكرار الكود المشترك:
class Person:
def __init__(self, name):
self.name = name
def introduce(self):
return f"أنا {self.name}"
class Teacher(Person):
def __init__(self, name, subject):
super().__init__(name)
self.subject = subject
def introduce(self):
return f"أنا {self.name}، أدرّس {self.subject}"
3. تعدد الأشكال (Polymorphism)
لاحظ في المثال السابق أن Teacher أعاد تعريف الدالة introduce. إذا كانت لدينا قائمة فيها أشخاص ومعلمون، واستدعينا introduce() لكل عنصر، فسيتصرف كل كائن حسب صنفه. البرنامج لا يحتاج إلى أن يسأل «هل هذا معلم أم طالب؟» قبل كل استدعاء. هذا يجعل الكود مرنًا وسهل التوسع: إذا أضفت صنفًا جديدًا مثل Parent لولي الأمر، فلن تحتاج إلى تعديل الحلقة.
مقارنة سريعة
| الموقف | الدوال والقواميس تكفي | الأصناف أنسب |
|---|---|---|
| حجم البرنامج | سكربت قصير لمهمة واحدة | تطبيق يكبر مع الوقت |
| نوع البيانات | بيانات بسيطة تمر عبر خطوات | كيانات لها حالة وسلوك: طالب، كورس، حساب |
| التكرار | لا توجد أنواع متشابهة كثيرة | أنواع متقاربة تشترك في خصائص ودوال |
| العمل الجماعي | مبرمج واحد | فريق يحتاج إلى حدود واضحة بين أجزاء الكود |
متى لا تحتاج إلى البرمجة كائنية التوجه؟
من الأخطاء الشائعة أن يتحمس المبتدئ فيحول كل شيء إلى أصناف، حتى البرنامج الذي يحول درجة حرارة. الأصناف أداة تنظيم، وليست هدفًا بذاتها. إذا كان برنامجك بسيطًا ويتكون من خطوات متتالية، فالدوال الواضحة تكفي وتكون أسهل في القراءة. ابدأ بالدوال كما شرحنا في مقال الدوال في بايثون، وعندما تلاحظ أنك تمرر المجموعة نفسها من البيانات إلى دوال كثيرة، فهذه إشارة إلى أن صنفًا قد يكون مفيدًا.
تمرين تصميم: كيف تفكر قبل أن تكتب؟
قبل كتابة أي صنف، جرّب هذه الطريقة البسيطة في التصميم. اكتب وصفًا قصيرًا للنظام بلغتك العادية، مثل: «في الأكاديمية طلاب يسجلون في كورسات، ولكل كورس مدرب ومجموعة دروس، ويحصل الطالب على درجة في كل اختبار». ثم ضع خطًا تحت الأسماء: طالب، كورس، مدرب، درس، اختبار. هذه مرشحة لتكون أصنافًا. وضع خطين تحت الأفعال: يسجل، يحصل على درجة. هذه مرشحة لتكون دوالًا خاصة بالكائنات. بعد ذلك اسأل عن كل صنف: ما البيانات التي يحملها؟ وما الذي يستطيع فعله؟ ومن يتعامل معه؟ ارسم الأصناف كمربعات على ورقة، وارسم أسهمًا بين المرتبط منها. هذا التفكير المسبق لعشر دقائق يوفر ساعات من إعادة كتابة الكود لاحقًا، ويكشف لك مبكرًا الأجزاء المتشابهة التي يمكن أن تشترك في صنف أب واحد عبر الوراثة.
أخطاء شائعة
- نسيان
self: كل دالة داخل الصنف تحتاج إلىselfكأول معامل، وإلا ستظهر رسالة خطأ عند الاستدعاء. - الخلط بين الصنف والكائن:
Studentهو القالب، وmariamهو الكائن. تستدعي الدوال على الكائن غالبًا. - وضع قائمة كقيمة افتراضية في المعاملات: مثل
def __init__(self, scores=[])، فتتشارك كل الكائنات القائمة نفسها دون أن تقصد. أنشئ القائمة داخل الدالة كما في مثالنا. - سلاسل وراثة طويلة: الوراثة لأكثر من مستويين أو ثلاثة تجعل الكود صعب الفهم.
تمارين للتطبيق
- أنشئ صنف
Bookفيه العنوان والمؤلف وعدد الصفحات، ودالة تعيد وصفًا للكتاب. - أنشئ صنف
BankAccountفيه الرصيد، ودالتان للإيداع والسحب، مع منع السحب إذا لم يكفِ الرصيد. - أنشئ صنف
Courseيحتوي على قائمة طلاب من صنفStudent، ودالة تعيد متوسط الفصل كله.
في مقال مشروع بايثون مع قاعدة بيانات SQLite نستخدم هذه الأفكار في تطبيق حقيقي يحفظ بياناته. وفي كورس بايثون في أكاديمية بدر التعليمية نبني مشروعات كاملة بالأصناف مع مراجعة من المدرب. ولمصادر إضافية زر المكتبة التعليمية، وجرّب أداة اكتشف مسارك لترتيب خطواتك القادمة.
الخلاصة
الصنف قالب، والكائن نسخة منه تحمل بياناتها ودوالها. التغليف يحمي البيانات، والوراثة تمنع التكرار، وتعدد الأشكال يجعل الكود مرنًا. استخدم الأصناف عندما يكبر برنامجك وتظهر فيه كيانات لها حالة وسلوك، واكتفِ بالدوال في البرامج البسيطة.
© 2026 أكاديمية بدر التعليمية – هذا المحتوى حصري لأكاديمية بدر التعليمية. يُسمح بالاقتباس القصير مع ذكر المصدر ورابط الصفحة.
القسم: البرمجة
التعليقات (0)
يمكنك التعليق بدون حساب، ويظهر تعليقك بعد مراجعة الإدارة، وقد تُعدّل الصياغة قبل النشر.
لا توجد تعليقات بعد – كن أول من يشارك.


أضف تعليقًا