Share
Explore

Kotlin Lab: Creating and Using Custom Exceptions

Kotlin Lab: Creating and Using Custom Exceptions

Objective

In this lab, you will learn how to effectively create and use Custom Exceptions in Kotlin, specifically within the context of the "Kotlin Snack Machine" application.

✅ Procedural Checklist to Create Custom Exceptions in Kotlin

Follow these steps carefully:

Step-by-step Checklist:

Define Custom Exception Class:
Create a class inheriting from Exception or a relevant subclass (e.g., RuntimeException).
class OutOfStockException(message: String) : Exception(message)

Integrate Exception into Your Application Logic:
Identify scenarios in your application where exceptions might be needed (e.g., invalid operations, resource limitations, invalid user actions).
Throw Custom Exception:
Throw your custom exception at the correct location within your method, clearly indicating the problem:
if (snack.quantity <= 0) {
throw OutOfStockException("${snack.name} is out of stock.")
}

Handle Exceptions Using Try-Catch:
Enclose code that may throw exceptions within a try-catch block:
try {
VendingMachine.purchaseSnack(customer, snackChoice)
} catch (e: OutOfStockException) {
println(e.message)
}

Test Exception Handling:
Run scenarios to ensure exceptions are handled gracefully and informatively.

Checklist : How to implement Custom Exceptions in Kotlin

Step 1: Define Relevant Custom Exceptions

class OutOfStockException(message: String) : Exception(message)
class InsufficientFundsException(message: String) : Exception(message)
class InvalidSelectionException(message: String) : Exception(message)

Step 2: Throw Custom Exceptions in the Snack Machine

Modify the purchaseSnack() method:
fun purchaseSnack(customer: Customer, snackIndex: Int) {
if (snackIndex !in snacksInventory.indices) {
throw IllegalArgumentException("Invalid selection.")
}

val snack = snacksInventory[snackIndex]

if (snack.quantity <= 0) {
throw OutOfStockException("${snack.name} is out of stock.")
}

if (customer.cashInWallet < snack.price) {
throw InsufficientFundsException("${customer.name} doesn't have enough money for ${snack.name}.")
}

// Successful transaction
customer.cashInWallet -= snack.price
cashInMachine += snack.price
snack.quantity -= 1
customer.snacksInKnapsack.add(snack.name)

println("Thank you, ${customer.name}! You purchased a ${snack.name}.")
}

Step 2: Implement Try-Catch in Main

fun main() {
val customer = Customer("Alice", 5.0)
VendingMachine.displaySnacks()

try {
VendingMachine.purchaseSnack(customer, 0) // Attempt to buy first snack
} catch (e: OutOfStockException) {
println("Sorry: ${e.message}")
} catch (e: IllegalArgumentException) {
println("Error: ${e.message}")
} catch (e: Exception) {
println("Unexpected error: ${e.message}")
}
}

Benefits of Custom Exception Hierarchies:

Clarity: Clearly communicates specific error conditions, aiding debugging and user experience.
Robustness: Encourages handling potential error conditions proactively.
Maintainability: Easily extend or modify exception handling as application requirements grow.
SOLID Compliance: Facilitates clear separation of concerns and adherence to Open/Closed principles through hierarchical exception design.
Use this lab to practice writing effective, maintainable Kotlin applications by strategically leveraging custom exceptions.
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.