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