Is there a way to use Contracts between val fields?

This is a simple class that store result or exception, but I can’t find a best way to handle those two fields without null-check at once. If we can use Contracts inside a class or even Contracts description can accept val field, that will be nice.

class ResultOrException<out R : Any, out E : Throwable> {
    constructor(result: R) {
        this.result = result
        this.exception = null
    }

    constructor(exception: E) {
        this.result = null
        this.exception = exception
    }

    @JvmField
    val result: R?

    @JvmField
    val exception: E?
}

val not allowed in Contracts description. (Of couse this make no sense, the field is nullable.)

fun <R : Any, E : Throwable> ResultOrException<R, E>.result(): R? {
    contract {
        //Error in contract description: only references to parameters are allowed in contract description
        returns(null) implies (exception != null)
    }
    return result
}

I used to have such classes, too, when I was writing Java. In Kotlin, the idiomatic way to do this is with sealed classes:

sealed class Result<T>
class Value<T>(val value: T) : Result<T>()
class Error(error: Throwable) : Result<Nothing>()

Now the usage looks as follows:

val result: Result<String> = computeFoo()
when (result) {
    is Error -> print(result.error) 
    is Value -> print(result.value)
}

I ommited the throwable’s type parameter for brevity.

3 Likes

Great! I used to tried in the way, but I forgot generic can be appied to sealed class.
now this question should be solved: How to make sealed classes generic in kotlin? - Stack Overflow