ما هي البرمجة الكائنية التوجيهية؟

البرمجة الكائنية التوجيهية (Object-Oriented Programming أو اختصاراً OOP) هي نمط من أنماط البرمجة يعتمد على مفهوم الكائنات (Objects). بدلاً من كتابة الكود كسلسلة من التعليمات، تقوم بتقسيم البرنامج إلى وحدات مستقلة تمثل الأشياء الحقيقية أو المفاهيم المجردة.

فكرة OOP الأساسية هي تعكس الطريقة التي نفكر بها في العالم الحقيقي. عندما ننظر إلى أي شيء حولنا، نراه كائن له خصائص (مثل اللون والحجم) وسلوكيات (مثل التحرك أو التغير). البرمجة الكائنية تتيح لك تمثيل هذه الأشياء في الكود البرمجي بشكل طبيعي ومنطقي.

من أكثر لغات OOP شيوعاً: Python و Java و C++ و C# و Ruby. جميع هذه اللغات تدعم مفاهيم OOP الأساسية، على الرغم من اختلاف تنفيذها في كل لغة.

لماذا نستخدم OOP؟

البرمجة الكائنية توفر العديد من المزايا التي تجعل الكود أسهل في القراءة والصيانة والتوسع. من أبرز هذه المزايا:

  • تنظيم الكود: تقسيم البرنامج إلى وحدات منطقية مستقلة
  • إعادة الاستخدام: استخدام نفس الكود في أماكن متعددة عبر الوراثة
  • الصيانة: سهولة تعديل جزء واحد دون التأثير على الأجزاء الأخرى
  • قابلية التوسع: إضافة ميزات جديدة بسهولة عبر الوراثة والتركيب
  • ال debug: اكتشاف الأخطاء أسهل عندما يكون الكود منظماً في وحدات

الفئات والكائنات

الفئة (Class) هي القالب أو المخطط الذي يتم إنشاء الكائنات منه. تحدد الفئة الخصائص (البيانات) والسلوكيات (الدوال) التي سيملكها الكائن.

الكائن (Object) هو النسخة الفعلية من الفئة. يمكنك التفكير في الفئة كقالب صب، والكائن هو المنتج النهائي الذي يخرج من هذا القالب.

مثال عملي:

# تعريف فئة
class Car:
    def __init__(self, brand, model, year):
        self.brand = brand    # خاصية
        self.model = model    # خاصية
        self.year = year      # خاصية
        self.speed = 0        # خاصية افتراضية

    def drive(self, speed):   # سلوك (دالة)
        self.speed = speed

    def stop(self):           # سلوك (دالة)
        self.speed = 0

# إنشاء كائنات من الفئة
car1 = Car("Toyota", "Camry", 2024)
car2 = Car("Honda", "Civic", 2023)

# استخدام الكائنات
car1.drive(100)
print(car1.speed)  # الناتج: 100

في هذا المثال، Car هي الفئة (القالب)، و car1 و car2 هما كائنات (نسخ فعلية) من هذه الفئة. كل كائن له خصائصه وقيمته الخاصة.

التغليف (Encapsulation)

التغليف هو مبدأ يختبئ البيانات والوظائف داخل الكائن، ويسمح بالوصول إليها فقط عبر واجهة محددة. هذا يحمي البيانات من التعديل العشوائي ويضمن سلامة البيانات.

في Python، يتم التغليف باستخدام:

  • خاص (private): يبدأ بشرطتين __variable — لا يمكن الوصول إليه من خارج الفئة
  • محمي (protected): يبدأ بشرطة واحدة _variable — يمكن الوصول إليه لكنه للداخل فقط بالأعراف
  • عام (public): بدون شروط variable — يمكن الوصول إليه من أي مكان

مثال:

class BankAccount:
    def __init__(self, balance):
        self.__balance = balance  # خاص (private)

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount

    def get_balance(self):       # واجهة للوصول
        return self.__balance

account = BankAccount(1000)
account.deposit(500)
print(account.get_balance())    # 1500
# print(account.__balance)      # خطأ! لا يمكن الوصول المباشر

الوراثة (Inheritance)

الوراثة تتيح لإنشاء فئة جديدة بناءً على فئة موجودة. الفئة الجديدة (الفئة الابنة) ترث جميع الخصائص والسلوكيات من الفئة الأصلية (الفئة الأب)، ويمكنها إضافة خصائص وسلوكيات جديدة أو تعديل الموجود منها.

الوراثة تساعد على إعادة استخدام الكود وتقلل التكرار. بدلاً من كتابة نفس الكود عدة مرات، يمكنك وضعه في فئة أب وتراثه في الفئات الابنة.

مثال:

# فئة أب
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        pass

# فئة ابنة
class Dog(Animal):
    def speak(self):
    return f"{self.name} يقول: ياو!"

class Cat(Animal):
    def speak(self):
    return f"{self.name} يقول: مياو!"

# استخدام الوراثة
dog = Dog("بيتي")
cat = Cat("نيمو")

print(dog.speak())  # بيتي يقول: ياو!
print(cat.speak())  # نيمو يقول: مياو!

التعددية (Polymorphism)

التعددية تعني أن نفس الدالة يمكن أن تعمل بطرق مختلفة حسب نوع الكائن المستخدم. هذا يتيح لك كتابة كود مرن وقابل للتوسع.

هناك نوعان رئيسيان من التعددية: التعددية الفرعية (compile-time) والتعددية اللحظية (runtime). في Python، نستخدم التعددية اللحظية بشكل أساسي.

مثال:

class Circle:
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14 * self.radius ** 2

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

# نفس الدالة، سلوك مختلف حسب الكائن
shapes = [Circle(5), Rectangle(4, 6)]

for shape in shapes:
  print(f"المساحة: {shape.area()}")

التجرد (Abstraction)

التجرد يعني إخفاء التفاصيل المعقدة وإظهار الوظائف الأساسية فقط. المستخدم لا يحتاج إلى معرفة كيف تعمل الدالة داخلياً، يكفي أن يعرف كيف يستخدمها.

على سبيل المثال، عندما تستخدم هاتفك، أنت تضغط على زر الكاميرا لالتقاط صورة. لا تحتاج إلى معرفة كيف تعمل الكاميرا داخلياً (العدسة، المستشعر، المعالج). هذا هو التجرد في العمل.

مثال باستخدام ABC في Python:

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14 * self.radius ** 2

# لا يمكن إنشاء كائن من Shape مباشرة
# shape = Shape()  # خطأ!

التركيب (Composition)

التركيب هو مبدأ يoman إنشاء كائنات معقدة عن طريق دمج كائنات أبسط. بدلاً من استخدام الوراثة، يمكنك إضافة كائنات أخرى كخصائص داخل كائن آخر.

القاعدة الذهبية هي: "افضّل التركيب على الوراثة" (Favor Composition over Inheritance). الوراثة تخلق ارتباطاً وثيقاً بين الفئات، بينما التركيب يوفر مرونة أكبر.

مثال:

class Engine:
    def __init__(self, horsepower):
        self.horsepower = horsepower

    def start(self):
        return "المحرك يعمل!"

class Car:
    def __init__(self, brand, horsepower):
        self.brand = brand
        self.engine = Engine(horsepower)  # تركيب

    def start(self):
      return f"{self.brand}: {self.engine.start()}"

car = Car("Toyota", 150)
print(car.start())  # Toyota: المحرك يعمل!

مبادئ SOLID

مبادئ SOLID هي خمسة مبادئ أساسية لتصميم البرمجيات الكائنية بشكل صحيح. هذه المبادئ تساعد في كتابة كود أسهل في الفهم والصيانة والتوسع.

المبدأ الاسم الشرح
S مبدأ المسؤولية الواحدة (Single Responsibility) كل فئة يجب أن تتحمل مسؤولية واحدة فقط
O مبدأ الفتح/الإغلاق (Open/Closed) الكائنات مفتوحة للامتداد، مغلقة للتعديل
L مبدأ بطلسكي (Liskov Substitution) يمكن استبدال الكائنات الأب بكائنات ابنة دون تغيير السلوك
I مبدأ الفصل (Interface Segregation) لا يجب إجبار الفئات على تنفيذ واجهات لا تستخدمها
D مبدأ عكس الاعتماد (Dependency Inversion) الเฟئات يجب أن تعتمد على التجريدات وليس التنفيذات

أنماط التصميم

أنماط التصميم (Design Patterns) هي حلول جاهزة لمشاكل شائعة في تصميم البرمجيات. هذه الأنماط تطورت على مدى سنوات من الخبرة في بناء الأنظمة البرمجية.

من أكثر الأنماط شيوعاً:

  • Singleton: ضمان عدم وجود أكثر من كائن واحد من نفس الفئة
  • Factory: إنشاء كائنات دون تحديد الفئة الدقيقة مسبقاً
  • Observer: إعلام الكائنات المشتركة عند تغيير حالة كائن آخر
  • Strategy: تعريف سلسلة من الخوارزميات وجعلها قابلة للتبادل
  • Decorator: إضافة سلوكيات جديدة للكائنات ديناميكياً

أمثلة عملية

لنر كيف تُستخدم مفاهيم OOP في مشاريع حقيقية:

نظام إدارة متجر:

class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price

class Cart:
    def __init__(self):
        self.items = []

    def add_product(self, product):
        self.items.append(product)

    def total(self):
        return sum(p.price for p in self.items)

class Customer:
    def __init__(self, name):
        self.name = name
        self.cart = Cart()  # تركيب

# استخدام
customer = Customer("أحمد")
customer.cart.add_product(Product("لابتوب", 50000))
customer.cart.add_product(Product("ماوس", 150))
print(f"المجموع: {customer.cart.total()}")

أسئلة شائعة عن البرمجة الكائنية

هل يجب أن أستخدم OOP في كل مشاريعي؟

ليس بالضرورة. OOP ممتازة للمشاريع الكبيرة والمعقدة، لكن للبرامج البسيطة أو السكريبتات، البرمجة الوظيفية قد تكون أس وأسرع. اختر النمط المناسب حسب حجم وطبيعة المشروع.

ما الفرق بين الوراثة والتركيب؟

الوراثة تخلق ارتباطاً وثيقاً بين الفئات (is-a relationship)، بينما التركيب يoman إضافة كائنات أخرى كخصائص (has-a relationship). التركيب يوفر مرونة أكبر ويُفضل عادةً.

هل Python لغة OOP كاملة؟

نعم، Python تدعم OOP بالكامل، لكنها أيضاً تدعم البرمجة الوظيفية والبرمجة الإجرائية. يمكنك استخدام أي نمط أو مزيج منها حسب احتياجاتك.

كيف أبدأ في تعلم OOP؟

ابدأ بفهم الفئات والكائنات أولاً، ثم انتقل إلى مفاهيم التغليف والوراثة. بعد ذلك، تعلم مبادئ SOLID وأنماط التصميم. الممارسة على مشاريع صغيرة أفضل طريقة للتعلم.

موارد ومقالات ذات صلة