Generics in Kotlin
📌 Generics in Kotlin
Generics in Kotlin provide a way to create classes, interfaces, and functions that can operate with different data types using type parameters. It allows for code reusability and ensures type safety during compile time.
✅ 1. Basic Syntax of Generics
In Kotlin, generics are defined using angle brackets (<>) with a type parameter.
📌 Syntax:
class Box<T>(val item: T) { fun (): T { return item }}fun () { val intBox = Box(10) val stringBox = Box("Hello, Kotlin!") println(intBox.getItem()) // Output: 10 println(stringBox.getItem()) // Output: Hello, Kotlin!}
Box<T>can store any type likeIntorString.
✅ 3. Generic Function
You can create functions that accept generic parameters using <T>.
📌 Example:
fun (data: fun () { printData(100) // Output: Data: 100 printData("Kotlin") // Output: Data: Kotlin printData(25.5) // Output: Data: 25.5}
<T>declares a generic type parameter for the function.
✅ 4. Multiple Type Parameters
You can use multiple type parameters like <T, U>.
📌 Example:
class PairData<T, U>(val first: T, val second: U) { fun () { println("First: $first, Second: fun () { val pair = PairData("Age", 30) pair.display() // Output: First: Age, Second: 30}
TandUcan hold different types.
✅ 5. Generic Constraints
You can restrict generic types using constraints with the : keyword.
📌 Example:
fun (value: T): fun () { println(square(4)) // Output: 16.0 println(square(5.5)) // Output: 30.25 // square("Kotlin") // Error: Type mismatch}
<T : Number>restrictsTto only accept Number types likeInt,Float, orDouble.
✅ 6. Covariance (out)
Use
outwhen a class produces data (Tcan only be returned).It is read-only.
📌 Example:
class Producer<out T>(private val data: T) { fun (): T = data}fun () { val producer: Producer<String> = Producer("Kotlin") println(producer.getData()) // Output: Kotlin}
outis used to ensure type safety when returning values.
✅ 7. Contravariance (in)
Use
inwhen a class consumes data (Tcan only be used as a parameter).It is write-only.
📌 Example:
class Consumer<in T> { fun (data: fun () { val consumer: Consumer<Number> = Consumer() consumer.printData(42) // Output: Data: 42 consumer.printData(3.14) // Output: Data: 3.14}
inis used for type flexibility when consuming values.
✅ 8. Generic Extension Functions
You can create generic extension functions that work on multiple data types.
📌 Example:
fun () { println("Type: ${this::class.simpleName}, Value: fun main() { 10.showType() // Output: Type: Int, Value: 10 "Kotlin".showType() // Output: Type: String, Value: Kotlin}
thisrefers to the calling object.
✅ Conclusion
Generics increase code reusability and ensure type safety.
Use
<T>for defining generic classes and functions.Apply constraints using
: ClassNamefor type restrictions.Use
outfor covariance when returning data.Use
infor contravariance when accepting data.Create flexible and reusable code using generics.