منصة التعليم الإلكتروني
جزء من قسم البرمجة كائنية التوجه في رحلة Java على Coddy. الدرس 84 من 87.
مرحبًا بك في فصل التحديات النهائية! صُممت هذه التحديات لاختبار إتقانك لجميع مفاهيم OOP التي تعلمتها طوال هذه الدورة.
في هذا التحدي، ستبني نظام منصة للتعلّم الإلكتروني يجمع بين الوراثة، والواجهات، وتعدد الأشكال، والتغليف، وأنماط التصميم في تطبيق متماسك.
يجب أن تُنمذج منصتك العلاقات بين courses والطلاب والمدرّسين. فكّر في كيفية توسيع User base class بواسطة صفتَي Student وInstructor، وكيف تحتوي courses على دروس، وكيف تعمل متابعة التسجيل بين الطلاب وcourses.
ضع في اعتبارك مبادئ البرمجة كائنية التوجه التي تنطبق: استخدم التغليف لحماية بيانات المستخدم، والوراثة لمشاركة السلوكيات المشتركة، والواجهات لتعريف العقود مثل Enrollable أو Completable، وتعدد الأشكال للتعامل مع أنواع المستخدمين المختلفة بطريقة موحّدة.
حظًا موفقًا في تطبيق كل ما تعلّمته!
التحدي
سهللنَبْنِ منصةً للتعلُّم الإلكتروني تجمع كل مفاهيم OOP التي أتقنتها طوال هذه الدورة! ستنشئ نظامًا يحاكي العلاقات بين الدورات والطلاب والمدرّسين باستخدام الوراثة والواجهات وتعدّد الأشكال والتغليف.
ستنظّم الكود عبر ستة ملفات:
Enrollable.java: أنشئ واجهةً تحدّد contract لعمليات التسجيل. يجب أن تعلن عن الدوالenroll(Student student)التي تُرجع قيمة منطقية، وgetEnrolledCount()التي تُرجع قيمة من النوع int.User.java: أنشئ class أساسية abstract تمثّل أي مستخدم على المنصة. أضف حقولًا private لـid(String) وname(String)، وconstructor يهيّئ كليهما، وgetters مناسبة، ودالة abstract هيgetRole()تُرجع String يصف دور المستخدم.Student.java: أنشئ class ترث منUser. أضف ArrayList private لتتبّع معرّفات الدورات المسجَّل فيها. أضف constructor يستدعي constructor الأب، ونفّذgetRole()لتُرجع"Student"، وأضف الدالتينaddCourse(String courseId)وgetEnrolledCourseCount(). أعد تعريفtoString()لتُرجع"Student: [name] ([enrolledCount] courses)".Instructor.java: أنشئ class ترث منUser. أضف حقلًا private لـspecialty(String). أضف constructor يستقبل id وname وspecialty، ونفّذgetRole()لتُرجع"Instructor"، وأضف getter لـ specialty، وأعد تعريفtoString()لتُرجع"Instructor: [name] - [specialty]".Course.java: أنشئ class تنفّذEnrollable. أضف حقولًا private لـcourseId(String)، وtitle(String)، وinstructor(Instructor)، وArrayList من الطلاب المسجَّلين. يستقبل constructor قيم courseId وtitle وinstructor. نفّذenroll(Student student)لإضافة الطالب إلى القائمة، واستدعِ دالة الطالبaddCourse()باستخدام معرّف هذه الدورة، ثم أعد true. نفّذgetEnrolledCount(). أضف دالةgetDetails()تُرجع معرّف الدورة بين قوسين مربعين حرفيين، يليه العنوان واسم المدرّس، على النحو المبني كـ"[" + courseId + "] " + title + " by " + instructorName.Main.java: أنشئ منصتك! ستتلقى سلسلةً مفصولةً بفواصل من الأوامر:ADD_INSTRUCTOR:id:name:specialtyADD_STUDENT:id:nameADD_COURSE:courseId:title:instructorIdENROLL:studentId:courseIdINFO:userId
احتفظ بـ collections للمدرّسين والطلاب والدورات. عالج كل أمر واطبع:
- ADD_INSTRUCTOR:
Instructor added: [name] - ADD_STUDENT:
Student added: [name] - ADD_COURSE:
Course added: [title] - ENROLL:
[studentName] enrolled in [courseTitle] - INFO: اطبع ناتج
toString()الخاص بالمستخدم
بعد جميع الأوامر، اطبع
--- Platform Summary ---متبوعًا بتفاصيل كل دورة وعدد المسجَّلين فيها بالتنسيق[courseDetails] - [count] student(s).
ستتلقى مُدخلًا واحدًا: سلسلة الأوامر المفصولة بفواصل.
على سبيل المثال، عند استخدام المُدخل ADD_INSTRUCTOR:I001:Dr. Smith:Java,ADD_STUDENT:S001:Alice,ADD_STUDENT:S002:Bob,ADD_COURSE:C001:OOP Fundamentals:I001,ENROLL:S001:C001,ENROLL:S002:C001,INFO:S001,INFO:I001، سيكون ناتجك:
Instructor added: Dr. Smith
Student added: Alice
Student added: Bob
Course added: OOP Fundamentals
Alice enrolled in OOP Fundamentals
Bob enrolled in OOP Fundamentals
Student: Alice (1 courses)
Instructor: Dr. Smith - Java
--- Platform Summary ---
[C001] OOP Fundamentals by Dr. Smith - 2 student(s)يجمع هذا التحدّي بين الوراثة (هرمية User)، والواجهات (Enrollable)، وتعدّد الأشكال (أنواع مستخدمين مختلفة لكل منها تطبيق toString الخاص بها)، والتغليف (حقول private مع وصول مضبوط) ضمن نظام متماسك!
جرّب بنفسك
import java.util.Scanner;
import java.util.HashMap;
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: إنشاء مجموعات لتخزين المحاضرين والطلاب والدورات
// تلميح: استخدم HashMap مع id كمفتاح للبحث السهل
// TODO: تقسيم المدخلات بواسطة الفاصلة للحصول على الأوامر المنفردة
// TODO: معالجة كل أمر:
// - ADD_INSTRUCTOR:id:name:specialty -> Create instructor, add to collection, print "Instructor added: [name]"
// - ADD_STUDENT:id:name -> Create student, add to collection, print "Student added: [name]"
// - ADD_COURSE:courseId:title:instructorId -> Create course with instructor, add to collection, print "Course added: [title]"
// - ENROLL:studentId:courseId -> تسجيل الطالب في الدورة، وطباعة "[studentName] enrolled in [courseTitle]"
// - INFO:userId -> البحث عن المستخدم (طالب أو محاضر) وطباعة toString() الخاصة به
// TODO: After processing all commands, print "--- Platform Summary ---"
// TODO: لكل دورة، اطبع "[courseDetails] - [count] student(s)"
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات الـ OOP
الملفات الخارجيةمقدمة في الـ OOPالفئات (Classes) مقابل الكائنات (Objects)الكلمة المفتاحية thisالدوال (Methods)الحقول (Attributes)دالة البناء (Constructor)تعدد أشكال دالة البناء (Constructor Overloading)مراجعة - آلة حاسبة بسيطة4الوراثة
الوراثة الأساسية (extends)الكلمة المفتاحية superإعادة تعريف الدوال (@Override)تسلسل المنشئات (Constructor Chaining)كلاس Objectالوراثة الأحادية ومتعددة المستوياتلماذا لا توجد وراثة متعددة للكلاساتمراجعة - هيكلية الموظفين7الدوال الخاصة وفئة Object
دالة toString()equals() و hashCode()دالة clone()compareTo() و Comparableواجهة Comparatorمراجعة - الترتيب المخصص2محددات الوصول والتغليف
نظرة عامة على مستويات الوصولدوال Getter و Setterإخفاء البياناتالكلمة المفتاحية finalمراجعة - مدير الحساب البنكي5تعدد الأشكال (Polymorphism)
أساسيات الـ Method Overloadingالـ Method Overriding (في وقت التشغيل)الـ Upcasting والـ Downcastingمعامل الـ instanceofالفئات والدوال المجردة (Abstract)مراجعة - حاسبة الأشكال8مفاهيم OOP المتقدمة
الـ Composition مقابل الـ Inheritanceالـ Aggregation مقابل الـ Compositionالفئات الداخلية والمتداخلة والمجهولة (Inner, Nested & Anonymous)الـ Enums ودوالهاالـ Records (Java 16+)الـ Sealed Classes (Java 17+)11أنماط التصميم - الجزء الأول
مقدمة في أنماط التصميمنمط Singletonنمط Factoryنمط Builderنمط Observerنمط Strategy3خصائص الفئة والعضو الساكن
المتغيرات الخاصة بالكائن مقابل المتغيرات الساكنةالدوال الساكنةالكتل البرمجية الساكنةالثوابت (static final)ملخص - العداد والأدوات المساعدة6الواجهات (Interfaces) والأصناف المجردة (Abstract Classes)
مقدمة في الواجهات (Interfaces)تنفيذ الواجهات (Interfaces)تنفيذ واجهات متعددةالـ Default و Static في الواجهاتالأصناف المجردة مقابل الواجهاتالواجهات الوظيفية (Functional Interfaces)مراجعة - نظام الدفع9الأنواع العامة (Generics)
مقدمة في الأنواع العامةالأصناف العامة (Generic Classes)الدوال العامة (Generic Methods)معاملات الأنواع المقيدةالرموز البديلة (?, extends, super)مراجعة - الحاويات العامة12أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبنمط المكررتدرّب بنفسك: مترجم Java عبر الإنترنت