Left Index

Kotlin Generics

Generics are the powerful features that allow us to define classes, methods and properties which are accessible using different data types while keeping a check of the compile-time type safety. Generics is pretty similar to Java but Kotlin developer has introduced two new keywords "out" and "in" to make Kotlin codes more readable and easy for the developer.


It is better to go for generic data type whenever we are not sure about the data type we are going to use in the application. Generally, in Kotlin generics is defined by <T> where "T" stands for template, which can be determined dynamically by Kotlin complier. In the following example, we will see how to use generic data types in Kotlin programming language.

Example:
package com.theitbulls.kotlinex

fun main(args: Array<String>) {
	var genericEx = GenericEx<String>("John")
	genericEx.displayInfo("Hello John");
	println()
	
	var genericEx1 = GenericEx<Int>(10)
	genericEx1.displayInfo("Hello 10");
	println()

	var genericEx2 = GenericEx<Float>(20f)
	genericEx2.displayInfo("Hello 20f");
	println()
	
	var genericEx3 = GenericEx<Number>(0304f)
	genericEx3.displayInfo("Hello 0304");
}


class GenericEx<T>(var value: T) {
	init {
		when (value) {
			is String -> println("Generic class for: String")
			is Int -> println("Generic class for: Int")
			is Float -> println("Generic class for: Float")
			is Number -> println("Generic class for: Number")
		}
	}

	fun <T> displayInfo(value: T) {
		when (value) {
			is String -> println("Type of value for(String): ${value}")
			is Int -> println("Type of value is for(Int): ${value}")
			is Float -> println("Type of value is (Float): ${value}")
			is Number -> println("Type of value is (Number): ${value}")
		}
	}
}
Output:
Generic class for: String
Type of value for(String): Hello John

Generic class for: Int
Type of value for(String): Hello 10

Generic class for: Float
Type of value for(String): Hello 20f

Generic class for: Float
Type of value for(String): Hello 0304

In above example we create GenericEx classs and create it's object with different-different data type like String, Int, Float and Number.

Kotlin Generics can be managed by the out and in keywords. In-variance is the property by which a standard generic function/class already defined for a particular data type, cannot accept or return another datatype. Any is the super-type of all other datatypes.

The out Keyword

In Kotlin, we can use the out keyword on the generic type which means we can assign this reference to any of its super types. The out value can only produced by the given class but can not consumed.


In below syntax, we have defined an GenericEx class that can produce a value of type T. Then, we can assign an instance of the GenericEx to the reference that is a super-type of it:

Without out keyowrd

Example:
package com.theitbulls.kotlinex

fun main(args: Array<String>) {
	var generic = GenericEx("Generics Ex")
	var ref: GenericEx<Any> = generic
	
	println(ref.get())
}


class GenericEx<out T>(val value: T) {
	fun get(): T {
		return value
	}
}
Output:
Generics Ex

The in Keyword

If we want to assign it to the reference of its sub type then we can use the in keyword on the generic type. The in keyword can be used only on the parameter type that is consumed, not produced:

Example:
package com.theitbulls.kotlinex

fun main(args: Array<String>) {
	val generic = GenericEx<Number>()
	val ref: GenericEx<Int> = generic
	
	println(ref.toString(20))
}


class GenericEx<in T> {
	fun toString(value: T): String{
		return value.toString()
	}
}

Here, we have declared a toString() method that only be consuming a value of type T. Then, we can assign a reference of type Number to the reference of its sub type - Int:


Note: If we have not used the in type in the above class, then given statement will produce a compiler error.