Kotlin Generics Explaind: Mastering in, out, and where

Anand Verma
3 min readFeb 28, 2023

--

Hey there, fellow Kotlin enthusiast! Today we’re going to talk about one of the most powerful features of Kotlin — Generics.

So, what are Generics? Generics are a way to write code that can work with multiple types without sacrificing type safety. This means that we can write code that can handle any type, without having to write separate code for each type.

To start with, let’s talk about “in” and “out”. These are keywords that help us define the relationship between generic types.

“In” keyword means that the generic type can only be used as a parameter for functions or methods, but not as a return type. It means that we can pass any subtype of the generic type as a parameter to the function, but we cannot return a subtype of the generic type.

“On the other hand, the “out” keyword means that the generic type can only be used as a return type, but not as a parameter. It means that we can return a subtype of the generic type, but we cannot pass a subtype of the generic type as a parameter to the function.

OUT

For example, let’s say we have a class Animal and two subclasses Dog and Cat. We can create a generic class AnimalShelter that can hold any subtype of Animal.

class AnimalShelter<out T: Animal>(val animals: List<T>) {
fun getAnimal(index: Int): T {
return animals[index]
}
}

Here, we have used the “out” keyword to define that the generic type T can only be used as a return type. This means that we can return a subtype of Animal (like Dog or Cat), but we cannot pass a subtype of Animal as a parameter to any function or method of the AnimalShelter class.

IN

Similarly, we can use the “in” keyword to define that the generic type can only be used as a parameter. For example, let’s say we have a class AnimalFeeder that can feed any type of Animal.

class AnimalFeeder<in T: Animal> {
fun feed(animal: T) {
animal.eat()
}
}

Here, we have used the “in” keyword to define that the generic type T can only be used as a parameter. This means that we can pass any subtype of Animal (like Dog or Cat) as a parameter to the feed function, but we cannot return a subtype of Animal from any function or method of the AnimalFeeder class.

WHERE

Now let’s talk about the “where” keyword. It is used to define constraints on generic types. We can specify that the generic type must be a subclass of a certain class, implement a certain interface or have a certain property.

For example, let’s say we have a function that takes a list of animals and returns the oldest animal. We can use the “where” keyword to define that the generic type T must be a subclass of the Animal class and implement the Comparable interface.

fun <T> findOldestAnimal(animals: List<T>): T where T: Animal, T: Comparable<T> {
return animals.maxOrNull()!!
}

Here, we have used the “where” keyword to define that the generic type T must be a subclass of the Animal class and implement the Comparable interface. This ensures that we can call the maxOrNull function on the list of animals and return the oldest animal.

To summarize, generics in Kotlin are a powerful feature that allows us to write code that can work with multiple types without sacrificing type safety.

Don’t forget to give it a clap and follow me. Have feedback or question let’s get connected by Clicking Here

--

--

Anand Verma

Discover the magic of mobile app development through the eyes of a tech-enthusiast and never-ending learner.