MURAT YENER: Generics provide type safety
and help you avoid explicit typecasts.
Generics extend the type system to allow a type or method
to operate on objects of various types
while providing compile time type safety.
On the other hand, generics can be
limiting when you need to access type info in a generic function
and the compiler tells you the info doesn't exist.
Kotlin once again has a more elegant way to deal with this.
In this video, I'll show you how to access
the type info of generic parameters
by using a single keyword--
reified.
If you like the video and want to see more videos like this,
just subscribe.
The missing type info is a result
of how generics are implemented in the JVM.
Hint, type erasure, which we will discuss later.
There's a workaround.
You can access the deleted generic type
by passing the class of the generics type
as a parameter of the function.
This isn't too bad, but Kotlin addresses the problem
with a unique keyword--
reified.
With reified, you can access the type info
from within a generic function.
If you are familiar with how generics work,
you might be asking how this is even possible.
Let's see how.
Let's talk about generics first.
Before generics were added to Java with version 5,
type info didn't exist in collections.
This means there is no indication
if an array list is an ArrayList of string, integer,
or any other type.
Without generics, each time you want
to access an object in a collection,
you need to perform an explicit cast.
Plus, there is no guard against invalid casts, which will
result in runtime exceptions.
To address this, generics were added in Java 5.
With generics, you can define a specific type for a collection,
and the compiler will warn you if you
try to add any other type.
Also, you don't need to perform explicit casts, which might
result in runtime exceptions.
Generics are implemented with a trick called type erasure.
Since there was no type info before Java 5,
the Java compiler first replaces all type info
with a base object type and its necessary type cast.
Type erasure allows both compile time type safety
by providing type information to the compiler,
as well as backwards comparability
by keeping the byte code the same as on previous Java
versions.
Meanwhile, type erasure can be limiting
when you need the typing for in a generic function.
Now, let's see how reified manages
to access type info at runtime that should have
been erased at compile time.
To tackle this problem, reified makes use of inline functions.
If you're unfamiliar with inline functions,
make sure you watch the inline functions video, which
is linked in the notes below.
To recap, if a function is marked as inline,
the Kotlin compiler will copy the function body
to every place where it is used.
One advantage of this is that the compiler is also
free to modify the function body as it's being copied over.
To use reified parameter types, you first
need to make the function inline and then
add the reified keyword to the generic parameter.
Let's take a look at what's happening
under the hood in the decompiled Java code.
When there's a call to the inline function
with a reified type, the compiler
will copy the function body and replace the generic types
with the actual declared type.
As a result, you don't need to pass the class
to access the type info.
Reified can be used only with inline functions,
so the same rules that apply to inline functions
apply to reified.
Also, keep in mind that reified functions cannot be accessed
from Java.
Java doesn't support in-lining, and without in-lining,
generic parameters cannot escape being erased by the compiler.
Reified also allows overloading functions
to return generic types.
For example, the following function can return an int
or float.
Normally, a function cannot be overloaded with the same input
and have different return types.
With the inline functions, once again, the compiler
can replace the generic return type with the expected file
while copying the function body.
If you take a look at the decompiled Java code,
the compiler uses an integer type for the intCall variable
and uses float for the floatCall variable.
Reified allows you to do things with generics
which were previously not possible due to lack
of type info at runtime.
Use reified when you need the class type
info in your inline functions or to overload generic return
types.
Reified doesn't introduce any performance penalties,
but inlining a large function can.
Since a function needs to be inlined
in order to use reified types, don't
forget to keep your reified functions short
to avoid performance penalties, and follow the best
practices for inline functions.
Thanks for watching.
Go write beautiful Android apps with Kotlin,
and I'll see you next time.