```sealed interface EmptyResult { object Succe...
# getting-started
o
Copy code
sealed interface EmptyResult {
    object Success : EmptyResult
    class Failure(val error: Throwable) : EmptyResult
}

sealed class DeleteResult : EmptyResult
sealed class SetResult : EmptyResult
Why can’t I access SetResult.Success or DeleteResult.Success?
I want both of those classes to have those object and class available to them, so I can write 1 method that does something to both, this method
Copy code
inline fun EmptyResult.fold(
    onSuccess: () -> Unit,
    onFailure: (exception: Throwable) -> Unit,
): Unit = when (this) {
    is EmptyResult.Success -> onSuccess()
    is EmptyResult.Failure -> onFailure(error)
}
the method is available though
y
I think what you want is a typealias instead:
Copy code
typealias DeleteResult = EmptyResult
o
Hmm
k
It seems you want all classes that implement the
EmptyResult
interface to also have their own separate
Success
and
Failure
subclasses. That's not what you have though. The classes
Success
and
Failure
and also
DeleteResult
and
SetResult
are all directly implementing
EmptyResult
.
o
Right
Yes Klitos
That's what I want indeed
s
so the general concept is working, see https://pl.kotl.in/FOulfIFbG But the classes
DeleteResult
and
SetResult
seem confused. First you define subtypes of EmptyResult within the body, then outside of it, which isn't wrong but maybe not what you intended.
Success
and
Failure
aren't properties of
EmptyResult
but subtypes. It's also strange that
DeleteResult
and
SetResult
are sealed classes, because you can't instanciate those. You'd have to create subtypes to those as well, which is probably not what you've intended.
k
Youssef's idea of
typealias DeleteResult = EmptyResult
would work, but there would be no type safety to prevent a DeleteResult being assigned to a SetResult. Maybe what you want is a parameterized interface, something like
class DeleteResult : EmptyResult<DeleteResult>
o
I think separate interfaces will be just fine
why convolute such a simple thing
y
Oh yes parameterizing could do the trick here. Something like this:
Copy code
sealed interface EmptyResult<R> {
  class Success<R> private constructor(): EmptyResult<R>
  class Failure<R>(val error: Throwable) : EmptyResult<R>
  companion object {
    private val successObject = Success<Nothing>()
    // Reified to prevent R from being Nothing
    inline fun <reified R> Success(): EmptyResult.Success<R> = successObject as Success<R>
  }
}
object DeleteResultType
object SetResultType
typealias DeleteResult = EmptyResult<DeleteResultType>
typealias SetResult = EmptyResult<SetResultType>
This should be typesafe and allow you to treat
DeleteResult
and
SetResult
as if they were there own thing, while ensuring that they're assignment-incompatible.