Theoretical Paper
- Computer Organization
- Data Structure
- Digital Electronics
- Object Oriented Programming
- Discrete Mathematics
- Graph Theory
- Operating Systems
- Software Engineering
- Computer Graphics
- Database Management System
- Operation Research
- Computer Networking
- Image Processing
- Internet Technologies
- Micro Processor
- E-Commerce & ERP
- Dart Programming
- Flutter Tutorial
- Numerical Methods Tutorials
- Flutter Tutorials
- Kotlin Tutorial
Practical Paper
Industrial Training
Kotlin Generics
Generics are the powerful features that allow to define classes, methods, and properties etc. which can be accessed using different types. The type differences of classes, methods, etc. are checked at compile-time.
The generic type class or method is declared as parameterized type. A parameterized type is an instance of generic type with actual type arguments. The parameterized types are declared using angle brackets <> Generics are mostly used in collections.
Advantage of Generics
Following are the key advantages of using generics:
- Type-safety: Generic allows to hold only single type of object. Generic does not allow to store other object.
- Type casting is not required: There is no need to typecast the object.
- Compile time checking: Generics code is checked at compile time so that it can avoid any problems at runtime.
Let's see a problem without using the generics.
In this example, we create a Person class with primary constructor having single parameter. Now, we want to pass the different type of data in object of Person class (say Int type as Person(30) and String type as Person("40")). The primary constructor of Person class accept Int type Person(30) and regrets String type Person("40"). It generates a compile time error as type mismatch.
class Person (age:Int){ var age: Int = age init { this.age= age println(age) } } fun main(args: Array){ var ageInt: Person = Person(30) var ageString: Person = Person("30")// compile time error }
To solve the above problem, we use a generic type class which is a user defined class that accepts different type of parametersin single class. In above example, when the object of Person class is created using type Int as Person< Int>(30) and Person< String>("40"), it replaces the Person class of type T with Int and String respectively. Let's see an example of generic method. In this example, we are accessing the generic method of collection type (ArrayList). For doing this, we create two different objectsof ArrayList class arrayListOf< String>("Ashu","Ajay") and arrayListOf< Float>(10.5f,5.0f,25.5f) of String and Float types respectively. When we call the generic method < T>printValue(list: ArrayList< T>) using printValue(stringList), the type T of method < T>printValue(list: ArrayList< T>)will be replaced by String type. Similarly, when we call the generic method using printValue(floatList), the type T of method < T>printValue(list: ArrayList< T>) will replace by Float type. As extension function allows to add methods to class without inherit a class or any design pattern.
Let's rewrite the above code using generic type. A class Person of type < T> is a general type class that accepts both Int and String types of parameter.
In other words, the type parameter
class Person
Output:
30
40
Syntax of generic class
class_or_interface
Syntax of generic method
< Type>methodName(parameter: classType< Type>)
Kotlin generic example
fun main(args: Array< String>){
val stringList: ArrayList< String> = arrayListOf< String>("Ashu","Ajay")
val s: String = stringList[0]
println("printing the string value of stringList: $s")
printValue(stringList)
val floatList: ArrayList< Float> = arrayListOf< Float>(10.5f,5.0f,25.5f)
printValue(floatList)
}
fun < T>printValue(list: ArrayList
Output:
printing the string value of stringList: Ashu
Ashu
Ajay
10.5
5.0
25.5
Kotlin generic extension function example
In this example, we add a method printValue()to ArrayList class of generic type. This method is called form stringList.printValue() and floatList.printValue()of String and Float types respectively. As "this" keyword in extension function represent the current calling instance. When we call the extension function using stringList.printValue(), the this represents stringList instance containing String type values. Similarly, calling the extension function using floatList.printValue(), the this represents floatList instance containing Float type values.
fun main(args: Array< String>){
val stringList: ArrayList< String> = arrayListOf< String>("Ashu","Ajay")
stringList.printValue()
val floatList: ArrayList< Float> = arrayListOf< Float>(10.5f,5.0f,25.5f)
floatList.printValue()
}
fun < T>ArrayList< T>.printValue(){
for(element in this){
println(element)
}
}
Output:
Ashu
Ajay
10.5
5.0
25.5