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]