منصة التعليم الإلكتروني
جزء من قسم Object Oriented Programming في رحلة Java على Coddy — الدرس 84 من 87.
مرحباً بك في فصل التحديات النهائية! تم تصميم هذه التحديات لاختبار إتقانك لجميع مفاهيم OOP التي تعلمتها طوال هذه الدورة.
في هذا التحدي، ستقوم ببناء نظام منصة تعليم إلكتروني يجمع بين الوراثة (inheritance)، والواجهات (interfaces)، وتعدد الأشكال (polymorphism)، والتغليف (encapsulation)، وأنماط التصميم (design patterns) في تطبيق متماسك.
يجب أن تقوم منصتك بنمذجة العلاقات بين الدورات والطلاب والمدربين. فكر في كيفية توسيع الفئة الأساسية User بواسطة فئتي Student و Instructor، وكيف تحتوي الدورات على دروس، وكيف يعمل تتبع الالتحاق بين الطلاب والدورات.
فكر في أي من مبادئ البرمجة كائنية التوجه (OOP) تنطبق: استخدم التغليف (encapsulation) لحماية بيانات المستخدم، والوراثة (inheritance) لمشاركة السلوك المشترك، والواجهات (interfaces) لتحديد العقود مثل Enrollable أو Completable، وتعدد الأشكال (polymorphism) للتعامل مع أنواع المستخدمين المختلفة بشكل موحد.
بالتوفيق في تطبيق كل ما تعلمته!
التحدي
سهللنقم ببناء منصة للتعلم الإلكتروني تجمع بين جميع مفاهيم البرمجة كائنية التوجه (OOP) التي أتقنتها طوال هذه الدورة! ستقوم بإنشاء نظام ينمذج العلاقات بين الدورات التدريبية والطلاب والمدربين باستخدام الوراثة، والواجهات (interfaces)، وتعدد الأشكال (polymorphism)، والتغليف (encapsulation).
ستقوم بتنظيم الكود الخاص بك عبر ستة ملفات:
Enrollable.java: أنشئ واجهة (interface) تحدد العقد لعمليات التسجيل. يجب أن تعلن عن الأساليبenroll(Student student)التي تعيد قيمة منطقية (boolean)، وgetEnrolledCount()التي تعيد قيمة صحيحة (int).User.java: أنشئ فئة أساسية مجردة (abstract base class) تمثل أي مستخدم على المنصة. قم بتضمين حقول خاصة (private) لـid(String) وname(String)، ومنشئ (constructor) يقوم بتهيئة كليهما، وجلب البيانات (getters) المناسبة، وطريقة مجردةgetRole()تعيد String يصف دور المستخدم.Student.java: أنشئ فئة ترث منUser. أضف ArrayList خاصًا لتتبع معرفات الدورات المسجل فيها. قم بتضمين منشئ يستدعي منشئ الفئة الأب، وقم بتنفيذgetRole()لتعيد"Student"، وأضف الأساليبaddCourse(String courseId)وgetEnrolledCourseCount(). قم بإعادة تعريف (Override) لـtoString()لتعيد"Student: [name] ([enrolledCount] courses)".Instructor.java: أنشئ فئة ترث منUser. أضف حقلًا خاصًا لـspecialty(String). قم بتضمين منشئ يأخذ id و name و specialty، وقم بتنفيذgetRole()لتعيد"Instructor"، وأضف getter للتخصص، وقم بإعادة تعريفtoString()لتعيد"Instructor: [name] - [specialty]".Course.java: أنشئ فئة تنفذ الواجهةEnrollable. قم بتضمين حقول خاصة لـcourseId(String)، وtitle(String)، وinstructor(Instructor)، و ArrayList من الطلاب المسجلين. يأخذ المنشئ 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
حافظ على مجموعات من المدربين والطلاب والدورات. قم بمعالجة كل أمر واطبع:
- 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 الخاص بها)، والتغليف (حقول خاصة مع وصول متحكم فيه) في نظام متماسك!
ورقة مرجعية
يجمع هذا التحدي النهائي بين مفاهيم متعددة للبرمجة كائنية التوجه (OOP) في نظام متماسك:
الواجهات (Interfaces)
تحديد العقود للسلوك الذي يجب على الفئات (classes) تنفيذه:
public interface Enrollable {
boolean enroll(Student student);
int getEnrolledCount();
}الفئات المجردة (Abstract Classes)
إنشاء فئات أساسية بسلوك مشترك وطرق (methods) مجردة:
public abstract class User {
private String id;
private String name;
public User(String id, String name) {
this.id = id;
this.name = name;
}
public abstract String getRole();
}الوراثة (Inheritance)
توسيع الفئات الأساسية لإنشاء أنواع متخصصة:
public class Student extends User {
private ArrayList<String> enrolledCourses;
public Student(String id, String name) {
super(id, name);
this.enrolledCourses = new ArrayList<>();
}
@Override
public String getRole() {
return "Student";
}
}تنفيذ الواجهات (Implementing Interfaces)
يمكن للفئات تنفيذ الواجهات للوفاء بالعقود:
public class Course implements Enrollable {
private ArrayList<Student> enrolledStudents;
@Override
public boolean enroll(Student student) {
enrolledStudents.add(student);
student.addCourse(courseId);
return true;
}
@Override
public int getEnrolledCount() {
return enrolledStudents.size();
}
}تعدد الأشكال (Polymorphism)
يمكن للفئات المختلفة تجاوز الطرق (methods) لتوفير سلوك متخصص:
@Override
public String toString() {
return "Student: " + name + " (" + enrolledCourses.size() + " courses)";
}التغليف (Encapsulation)
استخدم الحقول الخاصة (private fields) مع وصول محكوم من خلال الطرق (methods) لحماية سلامة البيانات والحفاظ على العلاقات بين الكائنات.
جرّب بنفسك
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: إنشاء مجموعات لتخزين المعلمين، والطلاب، والدورات التدريبية
// Hint: استخدم HashMap مع id كمفتاح لسهولة البحث
// TODO: تقسيم المدخلات بواسطة الفاصلة للحصول على الأوامر الفردية
// TODO: معالجة كل أمر:
// - ADD_INSTRUCTOR:id:name:specialty -> إنشاء معلم، وإضافته إلى المجموعة، وطباعة "Instructor added: [name]"
// - ADD_STUDENT:id:name -> إنشاء طالب، وإضافته إلى المجموعة، وطباعة "Student added: [name]"
// - ADD_COURSE:courseId:title:instructorId -> إنشاء دورة تدريبية مع معلم، وإضافتها إلى المجموعة، وطباعة "Course added: [title]"
// - ENROLL:studentId:courseId -> تسجيل طالب في دورة تدريبية، وطباعة "[studentName] enrolled in [courseTitle]"
// - INFO:userId -> البحث عن مستخدم (طالب أو معلم) وطباعة toString() الخاصة به
// TODO: بعد معالجة جميع الأوامر، اطبع "--- Platform Summary ---"
// TODO: لكل دورة تدريبية، اطبع "[courseDetails] - [count] student(s)"
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
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أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبنمط المكرر