What is in Keyword in Kotlin Generics Explained
in keyword is used to declare a type parameter as contravariant, meaning it can accept a supertype of the specified type. This allows a generic class or function to safely consume values of that type or its subtypes, enabling flexible and type-safe input handling.How It Works
Imagine you have a box that only takes items of a certain type. The in keyword in Kotlin generics tells the box it can accept items of the specified type or any of its supertypes. This is called contravariance.
Contravariance means you can use a more general type where a more specific type is expected. For example, if a function expects a box that can accept Number, you can give it a box that accepts Any because Any is a supertype of Number. This helps keep your code flexible and safe.
In Kotlin, in is used only for input positions (where values go into a generic type), ensuring you don't accidentally output values of the wrong type.
Example
This example shows a generic interface using in to accept values of type T or its supertypes safely.
interface Consumer<in T> {
fun consume(item: T)
}
class NumberConsumer : Consumer<Number> {
override fun consume(item: Number) {
println("Consumed number: $item")
}
}
fun feedNumbers(consumer: Consumer<Number>) {
consumer.consume(42)
consumer.consume(3.14)
}
fun main() {
val anyConsumer: Consumer<Any> = object : Consumer<Any> {
override fun consume(item: Any) {
println("Consumed any: $item")
}
}
// This line will cause a type mismatch error because Consumer<Any> is not a subtype of Consumer<Number>
// feedNumbers(anyConsumer) // Uncommenting this will cause a compilation error
val numberConsumer = NumberConsumer()
feedNumbers(numberConsumer) // Works
}When to Use
Use the in keyword when you want a generic type to only consume values (input) and not produce them (output). This is common in cases like event handlers, consumers, or processors where you only pass data in.
For example, if you have a function that accepts a generic consumer of data, marking the type parameter with in allows you to pass consumers that accept broader types safely. This increases flexibility without losing type safety.
Key Points
inmarks a generic type as contravariant, allowing supertypes as input.- It ensures type safety by restricting the generic type to input positions only.
- Commonly used for consumers or handlers that only take values.
- Improves flexibility by allowing broader types to be passed where narrower types are expected.
Key Takeaways
in keyword makes a generic type contravariant, accepting supertypes as input.in when your generic type only consumes values, not produces them.in restricts usage to input positions to avoid type errors.