Menu
CoddyTech

عملية الـ Upcasting

جزء من قسم البرمجة كائنية التوجه في رحلة C على Coddy. الدرس 31 من 61.

إن التحويل إلى النوع الأساسي هو التعامل مع نوع محدد (مشتق) على أنه نوعه الأكثر عمومية (الأساسي). في نموذج التركيب في C، يعني هذا تمرير مؤشر إلى بنية تضمّن نوعًا أساسيًا إلى دالة تتوقع النوع الأساسي.

تأمل بنية أساسية Vehicle وسيارة Car تحتوي عليها:

typedef struct {
    int speed;
} Vehicle;

typedef struct {
    Vehicle vehicle;  // النوع الأساسي بوصفه أول عضو
    int doors;
} Car;

تخيّل الآن دالة عامة تعمل مع أي مركبة:

void accelerate(Vehicle* v, int amount) {
    v->speed += amount;
}

بفضل قاعدة العضو الأول، يمكننا تمرير Car* إلى هذه الدالة عن طريق تحويله إلى Vehicle*:

Car my_car = {{0}, 4};  // speed=0، doors=4
accelerate((Vehicle*)&my_car, 50);
printf("Speed: %d\n", my_car.vehicle.speed);  // الناتج: 50

هذا هو التحويل إلى نوع أعمّ: ننتقل «إلى الأعلى» من نوع محدد إلى نوع عام. لا تعرف الدالة accelerate أنها تعمل مع Car؛ فهي لا ترى سوى Vehicle. يتيح لك هذا كتابة شيفرة قابلة لإعادة الاستخدام تعمل على النوع الأساسي، مع قبول أي نوع مشتق يتضمنه.

challenge icon

التحدي

سهل

لنبنِ نظام نقل بسيطًا يوضّح عملية التحويل إلى النوع الأساسي. ستنشئ نوعًا أساسيًا Vehicle ونوعًا أكثر تحديدًا Motorcycle، ثم تبيّن كيف يمكن لدالة عامة أن تعمل مع كليهما من خلال تحويل المؤشرات.

تكمن قوة التحويل إلى النوع الأساسي في أنه يمكنك كتابة دوال للنوع الأساسي، وستعمل بسلاسة مع أي نوع مشتق يضمّه. دراجتك النارية «هي مركبة»، لذا ينبغي أن تتمكن أي دالة تتوقع Vehicle* من معالجتها.

ستنظّم الشيفرة عبر ثلاثة ملفات:

  • vehicle.h: عرّف التسلسل الهرمي للبُنى مع حراس التضمين. أنشئ بنية Vehicle بحقلين: speed (عدد صحيح للسرعة الحالية) وmax_speed (عدد صحيح للسرعة القصوى للمركبة). ثم عرّف بنية Motorcycle التي تضم Vehicle بوصفه العضو الأول، وتضيف الحقل has_sidecar (عدد صحيح، حيث تعني 1 نعم و0 لا). صرّح عن دالتين: boost التي تأخذ Vehicle* ومقدارًا لزيادة السرعة، وprint_motorcycle التي تأخذ Motorcycle*.
  • vehicle.c: نفّذ الدالتين. ينبغي أن تزيد دالة boost سرعة المركبة بالمقدار المحدد، لكن يجب ألا تتجاوز max_speed؛ فإذا تجاوزت السرعة الجديدة الحد الأقصى، فعيّنها إلى max_speed بدلًا من ذلك. وينبغي أن تعرض دالة print_motorcycle جميع معلومات الدراجة النارية، بما فيها بيانات المركبة المضمّنة فيها.
  • main.c: أنشئ Motorcycle وتهيئة جميع حقولها. ثم وضّح التحويل إلى النوع الأساسي باستدعاء الدالة boost: حوّل Motorcycle* إلى Vehicle* لتمريره إلى هذه الدالة العامة. بعد زيادة السرعة، اطبع معلومات الدراجة النارية لرؤية النتيجة.

ستتلقى أربع قيم إدخال: السرعة الأولية للدراجة النارية، والسرعة القصوى لها، وما إذا كان لديها عربة جانبية (1 أو 0)، ومقدار زيادة السرعة.

ينبغي أن يبدو الناتج كما يلي:

Speed: 75
Max Speed: 120
Sidecar: Yes

حيث تمثل 75 السرعة بعد زيادة السرعة (50 الأولية + زيادة 25)، وتمثل 120 السرعة القصوى، وتشير Yes أو No إلى ما إذا كانت للدراجة النارية عربة جانبية. إذا كانت زيادة السرعة ستجعلها تتجاوز max_speed، فينبغي وضع حد للسرعة عند max_speed.

الفكرة الأساسية التي ستتعلمها هنا هي أن boost لا تعرف شيئًا عن الدراجات النارية. إنها تعمل فقط مع Vehicle. ومع ذلك، يمكن لدراجتك النارية، من خلال التحويل إلى النوع الأساسي، استخدام هذه الدالة العامة لتعديل بيانات المركبة المضمّنة فيها.

جرّب بنفسك

#include <stdio.h>
#include "vehicle.h"

int main() {
    int initial_speed, max_speed, has_sidecar, boost_amount;
    
    // اقرأ المدخلات
    scanf("%d", &initial_speed);
    scanf("%d", &max_speed);
    scanf("%d", &has_sidecar);
    scanf("%d", &boost_amount);
    
    // TODO: أنشئ Motorcycle وهيّئ جميع حقولها
    // تذكّر: يحتوي Motorcycle على Vehicle بوصفه العضو الأول فيه
    
    // TODO: وضّح التحويل إلى النوع الأب باستدعاء boost
    // حوّل Motorcycle* إلى Vehicle* لتمريره إلى الدالة boost
    
    // TODO: اطبع معلومات الدراجة النارية
    
    return 0;
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم C عبر الإنترنت