FLORINA MUNTENESCU: Short and easy to use,
default arguments allow you to implement function overloads
without the boilerplate.
Like many Kotlin features, this can feel like magic.
Are you curious to find out its secrets?
If you learn something new, like the video
and subscribe to the channel, but only if you think
we've earned it.
[MUSIC PLAYING]
If you need to overload the function instead
of implementing the same function multiple times,
you can use default arguments.
If you don't pass a value for the argument,
the default argument is used.
Default arguments can be applied to constructors as well.
They can be used similar to regular functions
with default arguments.
What happens when you call this from the Java programming
language?
Well, Java by default doesn't recognize the default value
overload.
To instruct the compiler to generate the overload methods,
use the @JvmOverloads annotation on your Kotlin function.
Now, both play of toy and play are visible in Java.
Want to see what's going on under the hood?
Let's look at the Java decompiled code
to see what the compiler generates for us--
so tools, Kotlin, show Kotlin bytecode, then
press the Decompile button.
We see that the compiler generates two functions--
play, that has one parameter, toy,
and is called when default arguments are not used,
and a synthetic method, play$default,
that has three parameters--
toy, an int, and an object.
It's called whenever the default arguments are used.
The object parameter is always null, but the value of int
differs.
Let's see how.
The value of the int parameter of play$default is computed
based on the number and the index of the arguments that
have a default argument passed in.
Based on the value of this parameter,
the Kotlin compiler knows with which parameters
to call the play function.
In our play example code, the argument at index 0
is using the default argument.
Therefore, play$default is called with var1,
is 2 of the power 0, so 1.
The play$default implementation that knows that the value
of var0 should be replaced with a default [? val. ?]
OK, let's take a more complex example
to see how the int parameter behaves.
Let's expand our play function, and at the call
site, use the default argument for doggo and toy.
Let's see what happened in the decompiled code.
We see now our int parameter is 5.
So here's how this was computed.
The parameters at positions 0 and 2
are using the default argument.
So var3 is 2 to the power 0, plus 2 to the power 2, so 5.
In bitwise AND operations, the parameters
are evaluated as such--
var3 and 1 is different than 0 is true, so var0 is goodDoggo.
var3 and 2 different than 0 is false, so var1 is not replaced.
And var3 and 4 is different than 0 is true, so var2--
getSqueakyToy.
Based on the bitmask applied to var3,
the compiler can compute which parameters should be
replaced with default values.
So in the examples above, we might have noticed that
the value of the object parameter is always null,
and that it's actually never used in the play$default
function.
This parameter is connected to supporting default values
in overriding functions.
So what happens when we want to override a function
with default arguments?
Let's change the example and make
play an open function of doggo and doggo an open class.
And let's create a new PlayfulDoggo class that extends
doggo and overrides play.
When we want to set a default value in PlayfulDoggo play,
we see that we are not allowed--
an overriding function is not allowed
to specify default values for its parameters.
OK.
So let's remove the override and check the decompiled code.
So we see a throw new UnsupportedOperationException,
"super calls with default arguments
not supported in this target, function play."
So does this mean that super calls with default arguments
will be supported in the future?
Well, we'll just have to wait and see.
For constructors, the decompiled Java code
has only one difference.
So constructors also create a synthetic method,
but instead of the object used in functions constructors
use a default constructor marker.
This parameter is called with null,
like the objects in functions.
Secondary constructors with default arguments
will also generate another synthetic method
using a default constructor marker,
like primary constructors.
Simple and sweet, default arguments
decrease the amount of boilerplate code
we need to write when dealing with overloaded methods,
allowing us to set default values for our parameters.
As is the case for a lot of Kotlin keywords,
we can understand their magic by picking
at the code it writes for us.
Check out our other Kotlin vocabulary videos for more.
Thanks for watching, and go write better Android apps
with Kotlin.
[MUSIC PLAYING]