الاستثناءات المخصصة
جزء من قسم البرمجة كائنية التوجه في رحلة Java على Coddy. الدرس 60 من 87.
تغطي الاستثناءات المضمّنة في Java العديد من سيناريوهات الأخطاء الشائعة، ولكنك تحتاج أحيانًا إلى استثناءات خاصة بنطاق تطبيقك. تتيح لك الاستثناءات المخصّصة إنشاء أنواع أخطاء ذات معنى توضّح بجلاء ما الذي حدث بشكل خاطئ.
لإنشاء استثناء custom، ما عليك سوى توسيع فئة استثناء موجودة. بالنسبة إلى استثناء checked، وسّع Exception:
public class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}بالنسبة إلى استثناء غير مُتحقَّق منه، قم بتوسيع RuntimeException:
public class InvalidAgeException extends RuntimeException {
public InvalidAgeException(String message) {
super(message);
}
}يمرّر استدعاء super(message) رسالة الخطأ إلى الصنف الأب، مما يجعلها متاحة من خلال getMessage(). يمكنك بعد ذلك استخدام throw وcatch مع الاستثناء custom الخاص بك مثل أي exception آخر:
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("Balance too low: " + balance);
}
balance -= amount;
}
// استخدامه
try {
account.withdraw(1000);
} catch (InsufficientFundsException e) {
System.out.println(e.getMessage());
}تجعل الاستثناءات المخصّصة التعليمات البرمجية أكثر قابلية للقراءة، وتسمح للجهات المستدعية بالتعامل مع حالات خطأ محددة بطرق مختلفة. وتكون قيمتها أكبر خصوصًا عند إنشاء واجهات API أو مكتبات، حيث يكون التواصل الواضح بشأن الأخطاء مهمًا.
التحدي
سهللنَبْنِ نظامًا لحجز التذاكر يستخدم الاستثناءات المخصصة للتعامل مع سيناريوهات الأخطاء المختلفة! ستنشئ أنواع استثناءات ذات معنى توضّح بوضوح ما الذي حدث بشكل خاطئ عند حجز التذاكر.
ستنظّم التعليمات البرمجية عبر أربعة ملفات:
TicketSoldOutException.java: أنشئ استثناءً مخصصًا checked (extendsException) للحالة التي لا تعود فيها التذاكر متاحة. يجب أن يقبل الاستثناء message في constructor الخاص به ويمرّره إلى parent class باستخدامsuper(message).InvalidSeatException.java: أنشئ استثناءً مخصصًا unchecked (extendsRuntimeException) للحالة التي يحاول فيها شخص ما حجز رقم مقعد غير صالح. يجب أن يقبل هذا الاستثناء أيضًا message ويمرّره إلى parent الخاص به.TicketBooth.java: أنشئ class يدير مبيعات التذاكر. يجب أن يتتبّع booth العدد الإجمالي للمقاعد المتاحة وأعلى رقم مقعد صالح. تضمّن:constructor يأخذ العدد الإجمالي للمقاعد المتاحة.
method
bookTicket(int seatNumber)يتحقق من صحة الحجز. إذا لم يتبقَّ أي تذاكر (كانت available seats تساوي 0 أو أقل)، اطرحTicketSoldOutExceptionمع message"No tickets remaining". إذا كان رقم المقعد أقل من 1 أو أكبر من إجمالي المقاعد، اطرحInvalidSeatExceptionمع message"Seat [seatNumber] does not exist". Otherwise، قلّل available seats بمقدار 1 واطبعBooked seat [seatNumber] successfully.method
getAvailableSeats()يعيد العدد الحالي للمقاعد المتاحة.Main.java: اجمع نظام التذاكر الخاص بك! ستتلقى مدخلين: العدد الإجمالي للمقاعد ورقم مقعد لحجزه.أنشئ
TicketBoothباستخدام إجمالي المقاعد given. ثم attempt إلى حجز رقم المقعد المحدد داخل كتلة try-catch. نظرًا لأنTicketSoldOutExceptionهو checked، يجب أن تتعامل معه. التقطTicketSoldOutExceptionfirst واطبعBooking failed: [exception message]. ثم التقطInvalidSeatExceptionواطبع التنسيق نفسه:Booking failed: [exception message].After كتلة try-catch، اطبع
Remaining seats: [count]باستخدام method getter.
ستتلقى مدخلين بالترتيب: إجمالي المقاعد (عدد صحيح) ورقم المقعد المراد حجزه (عدد صحيح).
لاحظ كيف تجبر الاستثناءات checked المستدعين على التعامل معها (باستخدام try-catch أو throws)، بينما لا تتطلب الاستثناءات unchecked معالجة صريحة. اختر نوع الاستثناء بناءً على ما إذا كان الخطأ شيئًا ينبغي للمستدعين توقّعه والتعافي منه!
جرّب بنفسك
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int totalSeats = scanner.nextInt();
int seatNumber = scanner.nextInt();
// TODO: قم بإنشاء TicketBooth بإجمالي المقاعد المعطى
// TODO: استخدم كتلة try-catch لمحاولة حجز المقعد
// - التقط TicketSoldOutException أولاً واطبع "Booking failed: [exception message]"
// - التقط InvalidSeatException واطبع "Booking failed: [exception message]"
// TODO: After the try-catch, print "Remaining seats: [count]"
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
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مراجعة - الترتيب المخصص10معالجة الاستثناءات في OOP
التسلسل الهرمي لفئات الاستثناءاتالاستثناءات المخصصةالأخطاء من نوع Checked مقابل Uncheckedنمط Try With Resourcesمراجعة - Validated User2محددات الوصول والتغليف
نظرة عامة على مستويات الوصولدوال 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 عبر الإنترنت