I have a Repository class that first tries to vali...
# announcements
s
I have a Repository class that first tries to validate something by going online, but if not available, falls back to an offline validator. I'm using sealed classes to return the state. Right now, return states are all in the same sealed class. I'd like to separate them so only the offline validator can return the offline ones, and only the online one can return online states. But I'd like the Repository to be able to return any of them (whether the validation happens online or offline matters to the upper layers, mainly for displaying to the user). How can I accomplish this?
Here is what I have now:
Copy code
sealed class ValidationResult {
    class ValidOnline: ValidationResult()
    class InvalidOnline: ValidationResult()
    class ValidOffline: ValidationResult()
    class InvalidOffline: ValidationResult()
}
I'd like something like:
Copy code
sealed class ValidationResult {
    sealed class Online: ValidationResult() {
        class Valid
        class Invalid
    }

    sealed class Offline: ValidationResult() {
        class Valid
        class Invalid
    }
}
t
Valid
and
Invalid
should extend the appropriate sealed class. This (surprisingly?) typechecks:
Copy code
sealed class ValidationResult {
    sealed class Online : ValidationResult() {
        object Valid : Online()
        object Invalid : Online()
    }
    sealed class Offline : ValidationResult() {
        object Valid : Offline()
        object Invalid : Offline()
    }
}

interface Validator {
    fun validate(): ValidationResult
}

object OnlineValidator : Validator {
    override fun validate(): <http://ValidationResult.Online|ValidationResult.Online> {
        return ValidationResult.Online.Invalid
    }
}

object OfflineValidator : Validator {
    override fun validate(): ValidationResult.Offline = TODO()
}
☝️ 1
Alternatively using generics:
Copy code
interface Validator <out T : ValidationResult> {
    fun validate(): T
}

object OnlineValidator : Validator <ValidationResult.Online> {
    override fun validate(): <http://ValidationResult.Online|ValidationResult.Online> = TODO()
}
r
You can use generics.
s
@Tsvetan Ovedenski The Validators type check, but then when I want to return any of those results from the Repository that would call them, it doesn't
I don't believe I can have a method that would be able to return both, say, ValidationResult.Online.Valid and ValidationResult.Offline.Invalid
t
The type signature of Validator::validate allows to return any of the 4 possible values. Now, implementers (apparently) can shrink this, as I've shown in the first example - Online can return only Online.Valid and Online.Invalid. Maybe I don't fully understand what you mean. Do you want to return Online.Invalid from Offline validator?
s
No, I wanted to prevent that. It seemed like it wasn't working when I tried that yesterday, but I'll try again. I didn't have the implementations specializing the return value