ikt
June 27, 2018, 9:58am
1
Hi, Is there a way to simplify the following code
sealed class Async_load_state<WaitT, ErrorT, DoneT> () {
class Wait<WaitT, ErrorT, DoneT>(val wait: WaitT): Async_load_state<WaitT, ErrorT, DoneT>() {}
class Error<WaitT, ErrorT, DoneT>(val error: ErrorT): Async_load_state<WaitT, ErrorT, DoneT>() {}
class Done<WaitT, ErrorT, DoneT>(val done: DoneT): Async_load_state<WaitT, ErrorT, DoneT>() {}
fun is_done(): Boolean {
return when(this) {
is Async_load_state.Error<*, *, *> -> true
is Async_load_state.Done<*, *, *> -> true
else -> false
}
}
}
class Async_load<WaitT, ErrorT, DoneT> (
val w: WaitT,
f: Async_load<WaitT, ErrorT, DoneT>.(WaitT) -> Unit) {
var state: Async_load_state<WaitT, ErrorT, DoneT> = Async_load_state.Wait<WaitT, ErrorT, DoneT>(w)
init { f(w) }
fun error(error: ErrorT) {
state = Async_load_state.Error<WaitT, ErrorT, DoneT>(error)
}
fun done(done: DoneT) {
state = Async_load_state.Done<WaitT, ErrorT, DoneT>(error)
}
}
Intuitively, <WaitT, ErrorT, DoneT> appears way too many times.
Thanks!
Use W
, E
and D
instead? Generic arguments are a single letter for a reason
Joking aside, generic parameters can easily propagate and explode - generics should be used judiciously
medium
June 28, 2018, 7:17am
4
Maybe you could use type aliases .
the problem with it is that you need to pass the generics from the base classes to the superclasses.
a type alias is not going to help with passing generics through
ikt
June 28, 2018, 11:44am
6
IIRC, in other languages, one can write this as:
data AsyncLoad WaitT ErrorT DoneT =
Wait WaitT | Error ErrorT | Done DoneT
where *T are type variables and Wait/Error/Done are constructors.
In this particular case I was not sure if:
There was an easier way to do this in Kotlin but I was unaware of it OR
Kotlin is slightly more verbose
It looks like we on agreeing on 2.
I do not really understand what your code should do. What are WaitT
ErrorT
and DoneT
should represent? It seems that they are used only internally, why make class generic at all?
1 Like
fvasco
June 28, 2018, 8:14pm
8
Can you replace
class Done<WaitT, ErrorT, DoneT>(val done: DoneT): Async_load_state<WaitT, ErrorT, DoneT>() {}
with
class Done<DoneT>(val done: DoneT): Async_load_state<Nothing, Nothing, DoneT>()
1 Like
Varia
June 30, 2018, 1:35pm
9
That would require all the type parameters to be declared out
. This would also result in any type Done<T>
to be a subtype of all Async_load_state<W,E,D>
, where T
is a subtype of D
, whereas in the current solution it would only be a subtype of a single instance type of Async_load_state
.