https://kotlinlang.org logo
Title
e

Eugen Martynov

08/30/2019, 1:13 PM
Would you go to
sealed class Operation(val value: Int) { class Add()...class Divide()}
or
class Operation(val type:Type, val value: Int)
where
Type
is enum?
s

Szymon Lipiński

08/30/2019, 1:16 PM
I'd always go in the direction of more detailed compiler checks (as long as it makes sense). So I'd use sealed classes here.
e

Eugen Martynov

08/30/2019, 1:17 PM
what is more detailed compiler check?
s

Szymon Lipiński

08/30/2019, 1:18 PM
If there is a sealed class and I want to use
when
with an object of this class, I need to check for all the subtypes or the code won't compile. It's really cool when I add a new type.
m

Marko Mitic

08/30/2019, 1:19 PM
sealed classes act as a enum in a when expression but can hold data unlike enums
e

Eugen Martynov

08/30/2019, 1:21 PM
exactly what Marco said - when expression works same for enum and sealed classes
s

Szymon Lipiński

08/30/2019, 1:22 PM
Yes, but you asked about using
sealed class
vs
class
. So in this case I'd use the sealed version. There was no enum in your question 🙂
e

Eugen Martynov

08/30/2019, 1:23 PM
ah sorry
Type
is enum in my example
m

Marko Mitic

08/30/2019, 1:24 PM
it depends on scenario, if all operations work with same value type, enums can work as well
otherwise, sealed classes are more flexible
s

Szymon Lipiński

08/30/2019, 1:25 PM
I see. I think in the general case I cannot see any advantage of one over another.
e

Eugen Martynov

08/30/2019, 1:26 PM
oke, my coworker wrote next
data class AppErrorNetwork(
        override val cause: Throwable
) : AppError()

data class AppErrorBackendRequest(
        override val cause: Throwable
) : AppError()

data class AppErrorUnknown(
        override val cause: Throwable,
        val message: String
) : AppError()
m

Marko Mitic

08/30/2019, 1:26 PM
and sealed classes can form hierarchies, like:
internal sealed class ProxyState {
    object NoProxy : ProxyState()
    sealed class Proxy(val info: ProxyInfo) : ProxyState() {
        class Initializing(info: ProxyInfo) : Proxy(info)
        class Active(info: ProxyInfo) : Proxy(info)
    }
}
Looks fine if
AppError
is sealed class
e

Eugen Martynov

08/30/2019, 1:30 PM
it is a sealed classes
for me the class is used as marker, I probably long time Java developer and user to have enum instead for marking type
m

Marko Mitic

08/30/2019, 1:33 PM
understood, give sealed classes a try, they are improvement over enum, same as
when
is over
switch
Your errors look modeled better as sealed classes as data isn't identical for each option
e

Eugen Martynov

08/30/2019, 1:35 PM
Data is almost same
BTW I work with kotlin over two years now, but this topic is always coming back
m

Marko Mitic

08/30/2019, 1:38 PM
I like sealed classes, I do find them useful to express various options
For example, that code I posted was an enum yesterday but was "upgraded" to sealed classes today
saved me a lot of null checks and `!!`s
e

Eugen Martynov

08/30/2019, 1:45 PM
did you have proxy info null with enum type? sure it is not nice
m

Marko Mitic

08/30/2019, 1:51 PM
yeah, I had few components that were not null only with Proxy so I wrapped them in ProxyInfo and voala, no null checks everywhere
e

Eugen Martynov

08/30/2019, 1:53 PM
nice!
m

Marko Mitic

08/30/2019, 1:54 PM
it's really flexible, I might have to add more data to Active or Initialized state and with sealed classes it will be no issue at all
or I could split Active into two states with different data
and my
when
expressions are super simple, compiler makes sure I covered all cases
all the benefits of enum without the restrictions