SPEAKER 1: One way to get some work done
is to delegate that work to another party.
No, I'm not talking about delegating your work
to your friend, but delegating work from one
object to another.
Guess what?
Delegation is not new to software.
[MUSIC PLAYING]
Delegation is a design pattern in which an object handles
a request by delegating to a helper object called
the delegate.
The delegate is responsible for handling the request on behalf
of the original object and making
the results available to the original object.
Kotlin makes delegation easier by providing support for class
and property delegates, and even containing
some built-in delegates of its own.
Let's start with class delegates.
Imagine you have a use case for an array list
that can recover its last removed item.
Basically, all you need is the same array list functionality
with a reference to the last removed item.
One way to do this is to extend the array list class.
Since this new class is extending the concrete array
list rather than implementing the mutable list interface,
it's highly coupled with the concrete array list
implementation.
Wouldn't be nice if you could overwrite the remove function
to keep a reference of the deleted item
and delegate the rest of the empty implementations
of mutable list to some other object?
Kotlin provides a way to achieve this
by delegating most of the work to an internal array list
instance and customizing its behavior.
To do this, Kotlin introduces a new keyword, by.
When you use the by keyword, Kotlin automatically
generates the call to use the inner list
instance as a delegate.
The by keyword tells Kotlin to delegate functionality
from mutable list interface to an internal array list
instance named innerList.
ListWithTrash still supports all the functions
in the mutable list interface by providing direct bridge methods
to the internal array list object.
Plus, now you have the ability to add your own behavior.
Let's see how this works.
If you take a look at the decompiled Java code,
you'll see that Kotlin compiler actually
creates wrapper functions that call
corresponding functions on the internal array list object.
Here, the Kotlin compiler uses another design pattern,
called the decorator pattern, to support class delegation
in the generated code.
In the decorator pattern, the decorator class
shares the same interface with the class to be decorated.
The decorator class keeps an internal reference
of the target class and wraps, or decorates,
all the public methods provided with the interface.
Delegates are especially useful when you can't inherit
from a particular class.
With class delegation, your class
is not part of any class hierarchy.
Instead, it shares the same interface
and decorates the internal object of the original type.
This means you can easily switch the internal implementation
without breaking the public API.
Besides class delegation, you can also
use the by keyword to delegate properties.
With property delegation, the delegate
is responsible for handling calls
to the get and set functions of the property.
This can be extremely useful if you
need to reuse the getter/setter logic across other object,
and lets you easily extend functionality
beyond simple backing fields.
Let's imagine you have a person class that's defined like this.
Let's say the name property of this class
has some formatting requirements.
When the name is set, you want to make
sure the first letter is capitalized while formatting
the rest in lowercase.
Also, when updating the name, you
want to automatically increment an updateCount property.
You could implement this functionality just like this.
While this works, what if the requirements change
and you want to increment updateCount each time
the last name changes, too?
You could copy paste the logic to write a custom setter,
but, suddenly you would find yourself
writing the same exact setter for each property.
Both setter methods are almost identical, telling you
one of them shouldn't exist.
With property delegation, we can reuse code
by delegating getters and setters to a property.
Let's see how.
Just like class delegation, you can use by keyword
to delegate a property, and Kotlin
will generate the call to use the delegate when
you use property syntax.
With this change, you've delegated the name and lastname
properties to the FormatDelegate() class.
Now let's take a look at the code for FormatDelegate().
The delegate class needs to implement read property
if you need to delegate only the getter,
or read/write property if you need to delegate
both the getter and the setter.
In our case, FormatDelegate() needs to implement read/write
property since you want to perform the formatting when
the setter is invoked.
You may have noticed there are two additional parameters
in the get and the set functions.
The first parameter is thisRef and represents the object
that contains the property.
thisRef can be used for accessing the object itself
for purposes such as checking other properties
or calling other class functions.
The second parameters is KProperty,
which can be used for accessing metadata
on the delegated property.
Looking back at the requirements,
let's use thisRef to access an increment update
count property.
To understand how this works, let's take a look
at the decompiled Java code.
The Kotlin compiler generates both the code
to keep private references of the FormatDelegate object
for name and lastname properties,
along with getters and setters that
contain the logic you edit.
The compiler also creates a KProperty array
to store the delegated properties.
If you take a look at the generated getters and setters,
the name properties start at index zero,
while the lastname properties start at index
one of the KProperty array.
With this trick, any caller can access the delegated property
with regular property syntax.
Kotlin not only supports delegates,
but also provides built-in delegates
in the Kotlin standard library.
We'll see that in more detail in another video, which
is, or will be, linked in the notes below.
Delegates can help you delegate tasks to other objects
and provide better [INAUDIBLE].
The Kotlin compiler creates the call
to let you use delegates seamlessly.
Kotlin uses simple syntax with the by keyword
to delegate a property or a class.
Under the hood, the Kotlin compiler
generates all the necessary code to support delegation
without exposing any change to the public API.
Simply put, Kotlin generates and maintains
all the needed boilerplate code for delegates.
Or in other words, you can delegate your delegates
to Kotlin.
Thanks for watching.
If you think you learned something new
and it was worth your time, hit the like button and subscribe.
Go write beautiful Android apps with Kotlin,
and I'll see you next time, which is soon.
[MUSIC PLAYING]