Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

การโยน Custom Exception ใน Kotlin

ภาพรวม

Exception ใน Kotlin ทั้งหมดสืบทอดมาจาก Throwable เหมือน Java แตกต่างคือ Kotlin ไม่มี Checked Exception (ไม่บังคับ try-catch หรือ throws) Custom Exception จัดอยู่ในกลุ่ม Unchecked Exception

Checked vs Unchecked Exception

ประเภทChecked ExceptionUnchecked Exception
ตรวจสอบเมื่อCompile TimeRuntime
ตัวอย่างIOException, FileNotFoundExceptionNullPointerException, ArithmeticException, Custom Exception
การจัดการบังคับ try-catch หรือ throwsไม่บังคับ (แต่ควรจัดการ)
ใน Kotlinไม่มี (ทุก Exception เป็น Unchecked)ทั้งหมด

สร้าง Custom Exception

// สร้าง Class สืบทอดจาก Exception
class MyCustomException(message: String) : Exception(message)

// หรือสร้างให้ละเอียดขึ้น
class ValidationException(
    message: String,
    val fieldName: String,
    val invalidValue: Any?
) : Exception(message) {
    // สามารถเพิ่ม Property เพิ่มเติมได้
}

ตัวอย่างการใช้งาน

fun main() {
    val sampleNumber = 100

    try {
        validateNumber(sampleNumber)
        println("Welcome!! You entered a correct value")
    } catch (e: MyCustomException) {
        println("Custom Exception: ${e.message}")
    } catch (e: Exception) {
        println("Other Exception: ${e.message}")
    } finally {
        println("Exception Handling in Kotlin")
    }
}

fun validateNumber(number: Int) {
    if (number > 50) {
        // โยน Custom Exception
        throw MyCustomException("Invalid Input - Please enter a number ≤ 50")
    }
}

class MyCustomException(message: String) : Exception(message)

ผลลัพธ์

Custom Exception: Invalid Input - Please enter a number ≤ 50
Exception Handling in Kotlin

Best Practices สำหรับ Custom Exception

1. Naming Convention

// ใช้ Suffix "Exception"
class InsufficientBalanceException(message: String) : Exception(message)
class UserNotFoundException(userId: String) : Exception("User not found: $userId")

2. เพิ่ม Context Information

class ApiException(
    val statusCode: Int,
    val responseBody: String?,
    message: String = "API Error"
) : Exception(message) {
    override fun toString(): String {
        return "ApiException(statusCode=$statusCode, body=$responseBody, message=$message)"
    }
}

3. Sealed Class สำหรับ Error Hierarchy (Modern Approach)

sealed class AppError {
    data class NetworkError(val cause: Throwable) : AppError()
    data class ValidationError(val field: String, val message: String) : AppError()
    data class ServerError(val code: Int, val message: String) : AppError()
    object UnknownError : AppError()
}

// ใช้งานกับ when (Exhaustive)
fun handleError(error: AppError) = when (error) {
    is AppError.NetworkError -> "Network issue: ${error.cause}"
    is AppError.ValidationError -> "Invalid ${error.field}: ${error.message}"
    is AppError.ServerError -> "Server error ${error.code}: ${error.message}"
    AppError.UnknownError -> "Unknown error"
}

4. ใช้ Result Type แทน Exception (Functional Style)

sealed class Result<out T> {
    data class Success<T>(val value: T) : Result<T>()
    data class Failure(val error: Throwable) : Result<Nothing>()
}

fun divide(a: Int, b: Int): Result<Int> {
    return if (b == 0) Result.Failure(ArithmeticException("Divide by zero"))
    else Result.Success(a / b)
}

สรุป

  • Custom Exception สืบทอดจาก Exception (Unchecked)
  • ใช้ throw เพื่อโยน Exception
  • ควรเพิ่ม Context/Property ให้ละเอียดเพื่อ Debugging
  • พิจารณา Sealed Class หรือ Result Type สำหรับ Error Handling แบบ Modern/Functional