0Pricing
Kotlin Academy · درس

إنشاء أصناف Exception مخصصة

عرّف استثناءات خاصة بالمجال برسائل وخصائص واضحة المعنى.

إنشاء أصناف Exception مخصصة درس مجاني في Kotlin Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Kotlin Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

لماذا نستخدم الاستثناءات المخصصة؟

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

أبسط استثناء مخصص

ورّث من Exception، أو من فئة فرعية محددة مثل RuntimeException، ومرّر رسالة إلى الباني الفائق.

class InvalidEmailException(message: String) : Exception(message)
fun main() {
    try {
        throw InvalidEmailException("missing @")
    } catch (e: InvalidEmailException) {
        println("caught: ${e.message}")
    }
}

استثناء مع خصائص

أضف حقولًا لنقل السياق، مثل حالة HTTP واسم الحقل وعدد محاولات إعادة الإرسال وغير ذلك.

class HttpError(
    message: String,
    val statusCode: Int
) : Exception(message)
fun main() {
    try {
        throw HttpError("Not Found", 404)
    } catch (e: HttpError) {
        println("HTTP ${e.statusCode}: ${e.message}")
    }
}

استثناء مع سبب

مرّر cause للحفاظ على الاستثناء الأصلي ضمن السلسلة.

class DatabaseError(message: String, cause: Throwable) : Exception(message, cause)
fun main() {
    try {
        try { error("connection refused") }
        catch (e: Throwable) { throw DatabaseError("query failed", e) }
    } catch (e: DatabaseError) {
        println("${e.message} (caused by: ${e.cause?.message})")
    }
}

الاستثناءات المفحوصة وغير المفحوصة

تتعامل Kotlin مع جميع الاستثناءات بوصفها غير مفحوصة، فلا يلزم التصريح باستخدام throws. ومن المتعارف عليه التوريث من RuntimeException.

class ValidationException(field: String, message: String) :
    RuntimeException("[$field] $message")
fun main() {
    try {
        throw ValidationException("age", "must be positive")
    } catch (e: ValidationException) {
        println(e.message)
    }
}

تسلسل استثناءات المجال

أنشئ تسلسلًا هرميًا حتى يتمكن المستدعون من التقاط نوع أساسي للمعالجة العامة أو أنواع فرعية محددة للحالات الخاصة.

open class AppException(message: String) : RuntimeException(message)
class NotFoundException(what: String) : AppException("$what not found")
class UnauthorizedException : AppException("not authorized")
fun main() {
    val errors = listOf(NotFoundException("user"), UnauthorizedException())
    for (e in errors) {
        try { throw e }
        catch (e: AppException) { println("App error: ${e.message}") }
    }
}

تسلسل استثناءات sealed

بالنسبة إلى مجموعات أنواع الأخطاء المغلقة، استخدم تسلسلًا هرميًا من نوع sealed، إذ يمكن للمستدعين معالجة كل تنويع بصورة شاملة.

sealed class ApiError(message: String) : RuntimeException(message) {
    class Timeout : ApiError("timeout")
    class NotFound(val id: String) : ApiError("not found: $id")
    class ServerError(val status: Int) : ApiError("server returned $status")
}
fun describe(e: ApiError) = when (e) {
    is ApiError.Timeout -> "request timed out"
    is ApiError.NotFound -> "id ${e.id} missing"
    is ApiError.ServerError -> "5xx: ${e.status}"
}
fun main() {
    println(describe(ApiError.NotFound("user-42")))
}

اصطلاح التسمية

أنه أسماء فئات الاستثناءات المخصصة بـ Exception أو Error لتوضيح الغرض. استخدم صيغة الماضي أو اسمًا، مثل NotFound وInvalidInput.

class InvalidInputException(msg: String) : RuntimeException(msg)
class UserNotFoundException(id: Int) : RuntimeException("user $id not found")
fun main() {
    try { throw UserNotFoundException(7) }
    catch (e: UserNotFoundException) { println(e.message) }
}

توثيق الاستثناءات

استخدم KDoc مع @throws لتوثيق الاستثناءات التي قد تطلقها الدالة.

/**
 * @throws InvalidEmailException if the email is malformed
 */
fun validate(email: String) {
    if ("@" !in email) throw InvalidEmailException("missing @")
}
class InvalidEmailException(m: String) : RuntimeException(m)
fun main() {
    try { validate("nope") }
    catch (e: InvalidEmailException) { println(e.message) }
}

تجنب الإفراط في استخدام الاستثناءات

تُستخدم الاستثناءات للحالات الاستثنائية. أما النتائج المتوقعة، مثل الإدخال الفارغ أو الحقل الاختياري المفقود، ففضّل لها القيم المرجعة القابلة لأن تكون null، أو أنواع النتائج sealed، أو القيم الافتراضية.

fun findUser(id: Int): String? = if (id == 1) "Alice" else null
fun main() {
    val name = findUser(42) ?: "(unknown)"
    println(name) // (unknown), no exception
}

مثال عملي

استثناء مخصص واقعي لعميل API افتراضي، مع الحالة والنص.

class ApiException(
    message: String,
    val statusCode: Int,
    val responseBody: String
) : RuntimeException(message)
fun main() {
    try {
        throw ApiException("Bad Request", 400, "{\"error\":\"invalid\"}")
    } catch (e: ApiException) {
        println("[${e.statusCode}] ${e.message}: ${e.responseBody}")
    }
}

تحقق سريع

ما الفئة الأب الأكثر استخدامًا عند تعريف استثناء Kotlin خاص بالمجال؟

مراجعة

تعبّر الاستثناءات المخصصة عن دلالة المجال. ورّث من RuntimeException أو Exception، وأضف خصائص للسياق، وحافظ على الأسباب، وأنشئ تسلسلات هرمية لالتقاط الاستثناءات المجمعة. استخدم الاستثناءات sealed للمجموعات المغلقة، وفضّل أنواع القيم القابلة لأن تكون null أو أنواع النتائج عندما تكون الأخطاء متوقعة.

الأسئلة الشائعة

هل درس «إنشاء أصناف Exception مخصصة» مجاني؟

نعم — نص درس «إنشاء أصناف Exception مخصصة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Kotlin Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

ماذا ستتعلم في «إنشاء أصناف Exception مخصصة»؟

عرّف استثناءات خاصة بالمجال برسائل وخصائص واضحة المعنى. تتمرن على Kotlin Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Kotlin Academy؟

لا تُشترط خبرة سابقة. Kotlin Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «إنشاء أصناف Exception مخصصة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Kotlin Academy هذا؟

نعم. كل درس في Kotlin Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. ‏try/catch/finally كتعبير
  2. إنشاء أصناف Exception مخصصة
  3. ‏runCatching وResult
  4. إعادة رمي الاستثناءات وتسلسلها
← العودة إلى Kotlin Academy