Kotlin Generics : How to get started with an example?
Kotlin Generics provide a way to design classes and functions that can operate on different types while maintaining type safety. With generics, you can write code that is more flexible and less prone to errors.
What are Kotlin Generics?
Generics are a useful tool found in many modern programming languages. They help make code more reusable by allowing us to create classes and functions that work with different types of data.
For example, when we use a List, the code inside the List doesn’t care about what type of data (T) we put in it. This flexibility makes it easier to write code that can be used with various types without repeating the same logic over and over again.
Advantages of Using Generics
Generics enable you to catch type errors at compile-time, preventing runtime type-related exceptions. The compiler ensures that the correct types are used throughout the code, reducing the chances of errors.
Code Reusability
By writing generic code, you can create components that work with various types, promoting code reuse and reducing duplication. This leads to more concise and maintainable codebases.
Abstraction
Generics allow you to abstract over types, enabling you to design flexible and extensible APIs. This enables the creation of libraries and frameworks that can be used with different data types.
Generics in Kotlin
Kotlin allows you to define classes with type parameters using the syntax class MyClass { … }. The type parameter T can be used within the class to represent a placeholder for a specific type. Instances of the class can then be created by specifying the actual type, such as val instance: MyClass = MyClass().
You can create classes and functions that work with multiple types, promoting code reuse and enhancing the maintainability of your codebase. With the ability to specify constraints and variance modifiers, Kotlin provides a comprehensive generics system that caters to a wide range of programming scenarios.
Simple Example of Generics in Kotlin
class InsideTheBox<T>(val item: T, val color: T){
fun getAnyItem(): T
{
return item
}
fun getAnyColor(): T
{
return color
}
}
In this code, InsideTheBox is a generic class that takes a type parameter T. The class has two properties: item and color, both of type T. These properties represent the item and color of something inside the box.
The class also has two member functions: getAnyItem() and getAnyColor(). Both functions return values of type T.
val fruitsInTheBox = InsideTheBox("Apple", "RED")
val noOfBoxesInside = InsideTheBox(2, 10010001)
val fruitsItems = "Item: ${fruitsInTheBox.getAnyItem()} \n Item Color: ${fruitsInTheBox.getAnyColor()}"
val noOfBoxes = "No of boxes : ${noOfBoxesInside.getAnyItem()} \n Color of box (Binary) ${noOfBoxesInside.getAnyColor()}"
println(fruitsItems)
println(noOfBoxes)
fruitsInTheBox is created with type arguments “Apple” and “RED“, which are both String types.
noOfBoxesInside is created with type arguments 2 and 10010001, which are an Int and Long type, respectively.
We then use the getAnyItem() and getAnyColor() methods on both instances to retrieve the values of the item and color properties.
The values are then concatenated into two separate strings: fruitsItems and noOfBoxes.
In this code, the generic class InsideTheBox allows us to create instances with different types, while still maintaining type safety and ensuring that the returned values match the types of the properties.
Full Program
class InsideTheBox<T>(val item: T, val color: T){
fun getAnyItem(): T
{
return item
}
fun getAnyColor(): T
{
return color
}
}
fun main()
{
val fruitsInTheBox = InsideTheBox("Apple", "RED")
val noOfBoxesInside = InsideTheBox(2, 10010001)
val fruitsItems = "Item: ${fruitsInTheBox.getAnyItem()} \n Item Color: ${fruitsInTheBox.getAnyColor()}"
val noOfBoxes = "No of boxes : ${noOfBoxesInside.getAnyItem()} \n Color of box (Binary) ${noOfBoxesInside.getAnyColor()}"
println(fruitsItems)
println(noOfBoxes)
}
Output
Item: Apple
Item Color: RED
No of boxes : 2
Color of box (Binary) 10010001
Kotlin generics provide a valuable tool for creating code that is flexible, type-safe, and can be reused effectively. By utilizing generics, you can design classes and functions that can handle different types of data, resulting in code that is more adaptable and easier to maintain.