FLORINA MUNTENESCU: Often, we need
to represent a limited set of possibilities.
A web request either succeeds or fails.
A user can only be a pro user or a standard user.
To model this, we could use an enum.
But this carries a number of limitations.
Enum classes only allow a single instance of each value
and can't encode more information on each type.
So for example, for the error case,
we can't have an associated exception.
You could use an abstract class and a number of extensions,
but this loses the restricted set of types advantage brought
by enums.
Sealed classes provide the best of both worlds--
the freedom of representation of abstract classes
and the restricted set of types of enums.
In this video, I'll tell you more
about how to use sealed classes, about the autocomplete power
brought by the ID, and we'll end by looking
under the hood at how sealed classes are implemented
in the decompiled Java code.
If you learn something new, like the video
and subscribe to the channel, but only if you think
we've earned it.
[MUSIC PLAYING]
Like abstract classes, sealed classes
allow you to represent hierarchies.
The child classes can be any type of class--
a data class, an object, a regular class, or even
another sealed class.
But unlike abstract classes, you have
to define these hierarchies in the same file
or as nested classes.
Trying to extend the sealed class outside the file
it was defined in yields a compile error.
Often, we want to handle all possible types.
But what if we need to add a new type of result,
like in progress.
Rather than relying on our bad memory and an ID search
to ensure that all when usages handle the new class,
the compiler can give us an error if a branch is uncovered.
When, like the if statement, only
requires us to cover all options--
so to be exhaustive-- by producing a compiler error
when it's used as an expression.
To get this code benefit even when
we're using when as a statement, add this helper extension
property.
So now, by adding .exhaustive, if a branch is missing,
the compiler will give us the same error we saw previously.
As all subtypes of a sealed class are known,
the ID can fill all possible branches
of a when statement for us.
But this autocomplete feature really
shines when we deal with more complex sealed
classes hierarchies.
SDID can recognize all branches.
So let's say that we have two types of error--
recoverable error and non-recoverable error.
So now our result has even more possible options.
The ID will generate all of these branches.
This is the type of functionality
that can't be implemented with abstract classes
as the compiler doesn't know the inheritance
hierarchy, therefore, the ID can't generate the branches.
So what makes sealed classes behave as they do?
Let's take a simple result example
and see what's going on in that decompiled Java code.
First, the metadata of the sealed class
keeps the list of the child classes,
allowing the compiler to use this information where needed.
The result is implemented as an abstract class
with two constructors-- a private default constructor
and a synthetic constructor that can only
be used by the Kotlin compiler.
So this means that no other class can directly
call the constructor.
If you look at the decompiled code of the success class,
we see that it calls through to the synthetic constructor.
That's all I have to say about sealed classes.
Start using them to model restricted class hierarchies,
allowing the compiler and the ID to help
you avoid the type errors.
Are you already using them?
Leave a comment below and tell us where and how.
Thanks for watching, and go write better Android apps
with Kotlin.
[MUSIC PLAYING]