Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

عملية الـ Upcasting

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

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

لنفترض وجود البنية الأساسية Vehicle وبنية Car التي تحتوي عليها:

typedef struct {
    int speed;
} Vehicle;

typedef struct {
    Vehicle vehicle;  // الأساس كعضو أول
    int doors;
} Car;

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

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

بفضل قاعدة العضو first، يمكننا تمرير 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

التحدي

سهل

لنَبْنِ نظام نقل بسيطًا يوضّح عملية الرفع إلى النوع الأساسي (upcasting) عمليًا. ستنشئ نوعًا أساسيًا Vehicle ونوعًا أكثر تخصيصًا Motorcycle، ثم توضّح كيف يمكن لـ function عامة العمل مع كليهما من خلال تحويل المؤشرات.

تكمن قوة الرفع إلى النوع الأساسي في أنه يمكنك كتابة دوال للنوع الأساسي، وستعمل بسلاسة مع أي نوع مشتق يضمّنه. دراجتك النارية «هي مركبة»، ولذلك ينبغي لأي دالة تتوقع 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 وinitialize جميع حقولها. ثم Demonstrate الرفع إلى النوع الأساسي عبر استدعاء دالة 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: وضّح الـ upcasting عن طريق استدعاء boost
    // حوّل Motorcycle* إلى Vehicle* لتمريره إلى دالة boost
    
    // TODO: اطبع معلومات الـ Motorcycle
    
    return 0;
}
quiz iconاختبر نفسك

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

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

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