What are Reified Types in Kotlin?
Since you are reading this blog, you must agree to the point that Kotlin is an awesome language and this is because of its unique features as compared to other programming languages. One of these features is the Reified keyword in Kotlin. Wait, what is this weird term called Reified? Don't worry, that's the topic for today's blog. In this blog, we are going to learn about Reified types. So, let's get started.
Before getting started
Most of the programming language has the concept of generics. Generics are used to provide a generic/general implementation of a class or a function or some properties i.e. you will write the implementation part once and use it for various data types.
For example, here is a code for a generic function:
fun <T> genericsExample(value: T) {
println(value)
}
fun main() {
genericsExample<String>("Learning Generics!")
genericsExample<Int>(100)
}
The above generic function can be used for any type of variable i.e for String, Int, Boolean, etc. So, the output of the above code will be:
Learning Generics!
100
Now, in the
genericsExample
function, let's try to find the type of
T
used i.e. let's have a print statement that will print if the type of
T
is String, Int, Boolean or something else.
fun <T> genericsExample(value: T) {
println(value)
prinln("Type of T: ${T::class.java}")
}
Is the above code working fine? No, you will be getting
Cannot use 'T' as reified type parameter
error. We can't get the info about the type T because of the
type erasure
thing in generics. So, if you want to access the type of
T
, then we can pass the class of the
T
as a parameter to the function
genericsExample
.
fun <T> genericsExample(classType: Class<T>, value: T) {
println(value)
println("Type of T: ${classType}")
}
fun main() {
genericsExample<String>(String::class.java, "Learning Generics!")
genericsExample<Int>(Int::class.java, 100)
}
But is it the best way to do this? Is it ok to use a boilerplate code like this? No, absolutely not.
So, here comes the role of the reified keyword in Kotlin. Let's learn about it.
Reified keyword in Kotlin
To access the information about the type of class, we use a keyword called
reified
in Kotlin. In order to use the reified type, we need to use the
inline function
.
If a function is marked as
inline
, then wherever the function is called, the compiler will paste the whole body of the function there. Learn more about inline from
here
.
So, here is the updated code(using reified types) of the above function that uses generics:
inline fun <reified T> genericsExample(value: T) {
println(value)
println("Type of T: ${T::class.java}")
}
fun main() {
genericsExample<String>("Learning Generics!")
genericsExample<Int>(100)
}
Here is the output of the above code:
Learning Generics!
Type of T: class java.lang.String
100
Type of T: class java.lang.Integer
So, what's happening under the hood? In order to find that, we need to see the bytecode of the above example:
public static final void genericsExample(Object value) {
int $i$f$genericsExample = 0;
boolean var2 = false;
System.out.println(value);
StringBuilder var10000 = (new StringBuilder()).append("Type of T: ");
Intrinsics.reifiedOperationMarker(4, "T");
String var4 = var10000.append(Object.class).toString();
boolean var3 = false;
System.out.println(var4);
}
public static final void main() {
Object value$iv = "Learning Generics!";
int $i$f$genericsExample = false;
boolean var2 = false;
System.out.println(value$iv);
String var5 = "Type of T: " + String.class;
boolean var3 = false;
System.out.println(var5);
Object value$iv = 100;
$i$f$genericsExample = false;
var2 = false;
System.out.println(value$iv);
var5 = "Type of T: " + Integer.class;
var3 = false;
System.out.println(var5);
}
Since we are using the
inline function
here, the code of the function will be copied and pasted wherever we will call the function. Also, the compiler is replacing the type
T
with the actual type i.e.
String
or
Int
. So, no need to pass the type explicitly. Isn't it awesome? Yeah, I know, it is. I told you at the starting of the blog ????.
NOTE: In Java, we can't use the reified function because inline function is not supported there.
Apart from the above feature, there are other things that can be done using reified. For example, we can use functions with the same arguments and name but different return type .
Functions with different return type
Think of a situation, where you want to keep the name, number, and type of arguments to the function as same but the return type as different. Can we do this by function overloading? Let's see.
For example, let's say you want to print some message if the marks of a student is above 90 and if the marks is below 90 you just want to return the marks. So, we can think of two functions with same name
showMessage
. The first function will take
marks
as input and will be called only when the
marks
is below 90 and this will just return the integer marks. Similarly, the other function will be called when
marks
is above 90 and will return some message as a string.
fun showMessage(marks: Int): Int {
return marks
}
fun showMessage(marks: Int): String {
return "Congratulations! you scored more than 90%";
}
The above overloaded function will throw an error because, for function overloading, the number of arguments or type of arguments should differ and not the return type.
So, we can use the
reified
keyword here. The modified code will look something like this:
inline fun<reified T> showMessage(marks: Int): T {
return when (T::class) {
Int::class -> marks as T
String::class -> "Congratulations! you scored more than 90%" as T
else -> "Please enter valid type" as T
}
}
fun main() {
val intMarks: Int = showMessage(70) // returning integer value
val stringMessage: String = showMessage(95) // returning string value
println("Your marks: $intMarks \nMessage: $stringMessage")
}
The output of the above code will be:
Your marks: 70
Message: Congratulations! you scored more than 90%
In the above example, you can see how we are using a
reified
keyword for returning different data types(Int and String in our example) from the same function.
This is how we use the reified keyword in Kotlin. I hope you enjoyed this blog. Do share this tutorial with your fellow developers to spread the knowledge.
Apply Now: MindOrks Android Online Course and Learn Advanced Android
Happy Learning :)
Team MindOrks!
Also, Let’s connect on Twitter , Linkedin , Github , and Facebook