1.1.50.13. fejezet, Lezárt osztályok és interfészek
Beküldte pzoli - 2024, április 22 - 3:51du
A lezárt osztályok és felületek biztosítják az osztályhierarchiák szabályozott öröklését. A lezárt osztály minden közvetlen alosztálya fordításkor ismert. Más alosztály nem jelenhet meg azon a modulon és csomagon kívül, amelyen belül a lezárt osztály definiálva van. Ugyanez a logika vonatkozik a lezárt interfészekre és azok implementációira: ha egyszer egy lezárt interfésszel rendelkező modult lefordítottak, nem lehet új implementációkat létrehozni.
A közvetlen alosztályok olyan osztályok, amelyek közvetlenül örökölnek szuperosztályukból. A közvetett alosztályok olyan osztályok, amelyek egynél több szinttel lejjebb örökölnek a szuperosztályuktól.
A lezárt osztályok leginkább olyan forgatókönyvekben használhatók, amikor:
- Korlátozott osztályú öröklésre van szükség: Van egy előre definiált, véges alosztálykészletünk, amely kibővíti az osztályt, és amelyek mindegyike ismert a fordításkor.
- Típusbiztos kialakításra van szükség: A biztonság és a mintaillesztés döntő fontosságú a projektben. Különösen az állapotkezeléshez vagy az összetett feltételes logika kezeléséhez.
- Zárt API-k használata: Robusztus és karbantartható nyilvános API-kat szeretne a kódtárakhoz, amelyek biztosítják, hogy a külső ügyfelek rendeltetésszerűen használják az API-kat.
// Create a sealed interface sealed interface Error // Create a sealed class that implements sealed interface Error sealed class IOError(): Error // Define subclasses that extend sealed class 'IOError' class FileReadError(val file: File): IOError() class DatabaseError(val source: DataSource): IOError() // Create a singleton object implementing the 'Error' sealed interface object RuntimeError : Error
Konstruktorok
sealed class Error(val message: String) { class NetworkError : Error("Network failure") class DatabaseError : Error("Database cannot be reached") class UnknownError : Error("An unknown error has occurred") } fun main() { val errors = listOf(Error.NetworkError(), Error.DatabaseError(), Error.UnknownError()) errors.forEach { println(it.message) } } // Network failure // Database cannot be reached // An unknown error has occurred
Interfészek
// Sealed interface 'Error' has implementations only in the same package and module sealed interface Error // Sealed class 'IOError' extends 'Error' and is extendable only within the same package sealed class IOError(): Error // Open class 'CustomError' extends 'Error' and can be extended anywhere it's visible open class CustomError(): Error
Lezárt osztályok használata a when kifejezéssel
// Function to log errors fun log(e: Error) = when(e) { is Error.FileReadError -> println("Error while reading file ${e.file}") is Error.DatabaseError -> println("Error while reading from database ${e.source}") Error.RuntimeError -> println("Runtime error") // No `else` clause is required because all the cases are covered }
Használati esetek forgatókönyvei
Állapotkezelés a felhasználói felületi alkalmazásokban
sealed class UIState { data object Loading : UIState() data class Success(val data: String) : UIState() data class Error(val exception: Exception) : UIState() } fun updateUI(state: UIState) { when (state) { is UIState.Loading -> showLoadingIndicator() is UIState.Success -> showData(state.data) is UIState.Error -> showError(state.exception) } }
Fizetési mód kezelése
sealed class Payment { data class CreditCard(val number: String, val expiryDate: String) : Payment() data class PayPal(val email: String) : Payment() data object Cash : Payment() } fun processPayment(payment: Payment) { when (payment) { is Payment.CreditCard -> processCreditCardPayment(payment.number, payment.expiryDate) is Payment.PayPal -> processPayPalPayment(payment.email) is Payment.Cash -> processCashPayment() } }
API-kérés-válasz kezelése
// Import necessary modules import io.ktor.server.application.* import io.ktor.server.resources.* import kotlinx.serialization.* // Define the sealed interface for API requests using Ktor resources @Resource("api") sealed interface ApiRequest @Serializable @Resource("login") data class LoginRequest(val username: String, val password: String) : ApiRequest @Serializable @Resource("logout") object LogoutRequest : ApiRequest // Define the ApiResponse sealed class with detailed response types sealed class ApiResponse { data class UserSuccess(val user: UserData) : ApiResponse() data object UserNotFound : ApiResponse() data class Error(val message: String) : ApiResponse() } // User data class to be used in the success response data class UserData(val userId: String, val name: String, val email: String) // Function to validate user credentials (for demonstration purposes) fun isValidUser(username: String, password: String): Boolean { // Some validation logic (this is just a placeholder) return username == "validUser" && password == "validPass" } // Function to handle API requests with detailed responses fun handleRequest(request: ApiRequest): ApiResponse { return when (request) { is LoginRequest -> { if (isValidUser(request.username, request.password)) { ApiResponse.UserSuccess(UserData("userId", "userName", "userEmail")) } else { ApiResponse.Error("Invalid username or password") } } is LogoutRequest -> { // Assuming logout operation always succeeds for this example ApiResponse.UserSuccess(UserData("userId", "userName", "userEmail")) // For demonstration } } } // Function to simulate a getUserById call fun getUserById(userId: String): ApiResponse { return if (userId == "validUserId") { ApiResponse.UserSuccess(UserData("validUserId", "John Doe", "john@example.com")) } else { ApiResponse.UserNotFound } // Error handling would also result in an Error response. } // Main function to demonstrate the usage fun main() { val loginResponse = handleRequest(LoginRequest("user", "pass")) println(loginResponse) val logoutResponse = handleRequest(LogoutRequest) println(logoutResponse) val userResponse = getUserById("validUserId") println(userResponse) val userNotFoundResponse = getUserById("invalidId") println(userNotFoundResponse) }
- A hozzászóláshoz be kell jelentkezni