Reputation: 41
I created a custom Result field (And not Kotlin's Result) in my service so I can return a message field in Both Success & Failure Cases:
sealed class Result<T> {
data class Success<T>(val value: T, val message: String) : Result<T>()
data class Failure<T>(val throwable: Throwable? = null, val message: String) : Result<T>() {
val isExceptional = throwable != null
val error: Throwable
get() = throwable ?: error("Error is undefined in [$this]")
}
}
Then in another class I called a method that produces this result and wanted to log Result.message
logger.info { "Finished with message [${result.message}]." }
Only, kotlin compiler doesn't recognize "message" since it's not a property of Result directly, but a property of Success and Failure.
I tried to override the message field and define it in Result class. But I get an Error.
Error:(10, 38) Kotlin: 'message' in 'Result' is final and cannot be overridden
So, how can one accesss Result.message without casting the result instance to it's derived implementing class (Success or Failure)?
Upvotes: 1
Views: 5422
Reputation: 6282
1- you can mark them open
open val message: String = ""
2- you can define them abstract
abstract val message: String
Upvotes: 1
Reputation: 1625
You can declare an abstract property in the Result
class:
sealed class Result<T> {
abstract val message: String
data class Success<T>(val value: T, override val message: String) : Result<T>()
data class Failure<T>(val throwable: Throwable? = null, override val message: String) : Result<T>() {
val isExceptional = throwable != null
val error: Throwable
get() = throwable ?: error("Error is undefined in [$this]")
}
}
Though, your solution is also an option
Upvotes: 3
Reputation: 41
A clean solution that I found is the following.
While Kotlin does not allow us to override sealed class members. It does allow us to override interface members.
So, I Created a simple interface for the message field, and implemented it from Result class:
interface ResultMessage {
val message: String
}
sealed class Result<T> : ResultMessage
// Now I'm able to override the message field simply, with no error
data class Success<T>(val value: T, override val message: String) : Result<T>()
data class Failure<T>(val throwable: Throwable? = null, override val message: String) : Result<T>() {
val isExceptional = throwable != null
val error: Throwable
get() = throwable ?: error("Error is undefined in [$this]")
}
Upvotes: 2