Skip to main content

Posts

Showing posts with the label kotlin

reified type in Kotlin

Introduction In Java, we have a type erasure problem where the runtime will not be able to preserve the type of the generic type that was intended and that will result in many times we having to pass the name of the class like Class<clz> ..  to provide the context information to perform the operations in generics. Type Erasure fun < T > getOnlyInts ( list : List < Any >): MutableList < T > { var result : MutableList < T > = mutableListOf () for ( item in list ) if ( item is T ) { result .add( item ) } return result } The above snippet of code illustrates the problem of type erasure where the type information for T is lost at runtime. this results in the type check failure in the line item is T Since the type data is erased , the runtime cannot figure out if it is performing the right type check. Hence the compilation fails. reiefied In Kotlin, we have the reified types which helps us to preserve the type information

sequences in Kotlin

Introduction Sequences in Kotlin are similar to that of the stream s in Java, where in the evaluation happens lazily and the volume of data processed in each step in the chain are reducing based on the met criteria. Sample Let us consider the below given sample data class data class Car ( val model : String , val year : Int ) We can create a collection of cars so that we can evaluate both and understand the difference between collections and sequence   in Kotlin var cars = listOf ( Car ( "Toyota" , 2021), Car ( model = "Tesla-S" , 2022), Car ( "Mercedes - Maybach" , 2022) ) Sequence In the below given snippet of code, we are performing the filtering of cars by name and then printing the year println ( cars . asSequence (). filter { it . model == "Toyota" } . map { it . year } This produces the output as given below kotlin.sequences.TransformingSequence@b97c004a This is because the sequence is lazy and is not evaluated as there is

when blocks in Kotlin

when This post shows multiple ways in which we can use the when  block in Kotlin We can start with a typical use of when (like in switch statements) enum class Season { SPRING , SUMMER , FALL , WINTER } To execute logic based on the season, we write the below snippet of code when ( timeOfYear ) { Season . SPRING -> println(" Flowers are blooming") Season . SUMMER -> println("It's hot!") Season . FALL -> println("It's getting cooler") Season . WINTER -> println("I need a coat") } In case we wanted to get the value rather than print based on the timeOfYear, we can use the below snippet of code, where we return the value and it can be returned in the overall when block val str = when ( timeOfYear ) { Season . SPRING -> "Flowers are blooming" Season . SUMMER -> "It's hot!" Season . FALL -> "It's getting cooler" Season . WINTER -> { "

Destructuring in Kotlin

Introduction This is a process in which we can be able to extract properties of interest from an object  / collection. We have been used to using destructuring in javascript and other functional languages whereas in Java / C# we have not been able to do this. However, kotlin has added the functionality to destructure classes by properties, collections, maps etc. Destructuring classes To enable a class to be destructured, should we do anything in kotlin? The answer is yes and no.. looks puzzling ain't it. Destructuring a class Below is a regular class (non data class) which needs implementation to allow it to be destructured class User ( var mail : String , var deptId : Long ) { operator fun component1 () = mail operator fun component2 () = deptId } Destructuring a data class Below is a declaration of a data class which comes with the support for destructuring for free as like toString, hashcode etc.. data class CompanyUser ( var mail : String , var deptId : Long ) Now that

enum in kotlin

ENUM Enums help us in defining like a fixed key-value pairs and then use them. These are to be used like fixed pairs and need not be stored in database or be something that shows up dynamically. These are mostly fixed entries. enum class ProductCategories ( val cat : String , val id : Int ) { ELECTRONICS ( "Electronics" , 0), ACCESSORIES ( cat = "Computer Accessories" , 1), PHERIPHERALS ( cat = "Computer Pheripherals" , id = 2); //This is a mandatory semi-colon fun getEnumId () = id fun categoryName () = cat } fun main (){ println ( ProductCategories . ACCESSORIES .categoryName()) println ( ProductCategories . PHERIPHERALS .categoryName()) }

anonymous objects in Kotlin

Anonymous Objects The benefit of using the anonymous objects is that they can be used to simplify usage rather than creating classes and then instantiating them and then consuming the functions. In this post, we are taking a simple interface and the interface is being used as an argument in a function. When we need to consume the method, we are required to create objects that are created from the classes that implement the interfaces. interface IPowerOfTwo { fun getPowerOf2 ( no : Int ): Int } fun printPowerOf2 ( powerOf2 : IPowerOfTwo ) { println ( "The value ^ 2 is : ${ powerOf2 .getPowerOf2(20) } " ) } Rather than creating the classes and instances, we can create an object on the fly and pass it as an argument to the function. fun main () { //The below method uses an anonymous object that has no class, yet implements the interface and gets the method ready for use printPowerOf2 ( object : IPowerOfTwo { override fun getPowerOf2 ( no : Int ) = no * n

Factory design pattern in Kotlin with companion objects

Factory Pattern The factory pattern helps the user to create the objects based on the inputs, so that the caller does not know how the object instances are created, instead focus on what are required to get me an instance of a given type. We start with a regular product, which has a constructor that takes the arguments and allows anyone to create the objects by invoking the appropriate constructor class RegularProduct { var skuId : String constructor ( sId : String ) { skuId = sId } constructor ( sId : String , upperCase : Boolean ) { skuId = if ( upperCase ) sId . toUpperCase () else sId . toLowerCase () } } //The private primary constructor restricts instantiation by any means other than factory class ProductWithFactory private constructor ( val sid : String ) { companion object { //Acts as a factory fun getProduct ( sid : String ): ProductWithFactory { return ProductWithFactory ( sid ) } fun getProduct ( si

Operations on Collections in Kotlin

Collections This post provides some of the operations that can be done in the collections using kotlin The below is the base type definitions that will be used in the below collection queries data class Shop ( val name : String , val customers : List < Customer >) data class Customer ( val name : String , val city : City , val orders : List < Order >) { override fun toString () = " $ name from ${ city . name } " } data class Order ( val products : List < Product >, val isDelivered : Boolean ) data class Product ( val name : String , val price : Double ) { override fun toString () = "' $ name ' for $ price " } data class City ( val name : String ) { override fun toString () = name } Operations on collections // Return a list of customers, sorted in the descending by number of orders they have made fun Shop. getCustomersSortedByOrders (): List<Customer> = this .customers.sortedByDescending( { it -> it.order

Range check in Kotlin

Introduction In many cases, we might be interested in checking dates to see if they fit in the range or numbers to see if they fall between the given range of numbers. Kotlin has a short hand way to represent the range which can be quite handy fun checkInRange(date: MyDate, first: MyDate, last: MyDate): Boolean {     return date in first..last } The above snippet of code is used to check the date (1st argument) lies between the first and the last date ranges.

Operator Overloading in Kotlin

Introduction The operator overloading feature let's us to build custom operators. In The below example, we provide a compareTo which can help us in evaluation of the <, >, = functions in the custom object of type MyDate data class MyDate( val year: Int , val month: Int , val dayOfMonth: Int ) : Comparable<MyDate> {     operator override fun compareTo(other: MyDate)= when {          year != other.year -> year - other.year         month != other.month -> month - other.month         else -> dayOfMonth - other.dayOfMonth     } } In the above snippet, we are implementing the Comparable<T>   for our MyDate type so that we can compare two instances of type MyDate as given below     println(date1 < date2) Capabilities This helps us in implementing custom operators to ease the use of business objects throughout the code rather than repeating code or using lots of Helpers in the code base.

Extension Functions in Kotlin

Introduction Extension functions help us a lot when implementing re-usable code. In many cases where we are required to provide re-usable code, but unable to add the function to the class may be because it was from a 3rd party library or from an external module, we end up adding a pile of helpers in getting the job done. In Java, this feature is not supported unlike in C# and other languages. The drawback of this is we have to create a helper class and create static methods which are not tied to the types. This results in helper classes being used and is not more readable than having the method as an extension or part of the type. data class RationalNumber( val numerator: Int , val denominator: Int ) fun Int.r(): RationalNumber = RationalNumber( this , 1 ) fun Pair< Int , Int >.r(): RationalNumber = RationalNumber( this .first, this .second) The above snippet explains the use of extension functions  which help us in extending the Integer and the Pair Types. After building t

Renaming types on Import

The following snippet of code illustrates how the rename functionality works in Kotlin after importing a type. import kotlin.random.Random as KRandom import java.util.Random as JRandom fun useDifferentRandomClasses(): String {     return "Kotlin random: " +             KRandom.nextInt( 2 ) +             " Java random:" +             JRandom().nextInt( 2 ) +             "." } In the above snippet of code, we see that we are importing two Random types. We are able to use KRandom for the type imported from Kotlin and JRandom for the type imported from java.util.Random

varargs and array destructuring in Kotlin

Introduction The following post illustrates the use of varargs (variable number of arguments) and array destructing feature in Kotlin langauge. varargs This feature allows multiple arguments of a same type to be passed to a method and not using a collection like Array or list. This feature in java is implemented using the 3 consecutive dots notation given below ... Java Example public String getByValues (String... values) { // ... } Array destructuring With array destructuring, we can be able to use the elements of the array without looping through or pulling out by index which needs careful access as we might get array out of bounds exceptions if not checked. Sample Code fun main() {     val c1 = Color( "red" )     val c2 = Color( "Blue" )     val c3 = Color( "Green" )     val colors = arrayOf(c1, c2, c3)     val manyColors = arrayOf(*colors, c2.copy())     printColors(c1, c2, c3, message = "The color is: " ) // variable number of arg

Kotlin Data Classes and Smart Casts

Introduction Kotlin is a language that is built by the Jetbrains team and opensource contributors. The following are the goals that this language helps us achieve (not full set, for more details please visit kotlinlang.org Modern, concise and safe programming language A productive way to write server‑side applications (still using the frameworks that target JVM) Cross-platform layer for native applications Big, friendly and helpful community Kotlin Data Classes Below I am giving some of the kotlin snippets and short descriptions on what they can perform. Keep in mind that kotlin achieves very concise code data class Person ( val name: String , val age: Int ){     } fun getPeople(): List <Person> {     return listOf(Person( "Alice" , 29 ), Person( "Bob" , 31 )) } fun comparePeople(): Boolean {     val p1 = Person( "Alice" , 29 )     val p2 = Person( "Alice" , 29 )     return p1 == p2   // should be true } In the snippet above, we

The Key from Stackoverflow

Introduction For many years, we have been dealing with memes like try{ doSomething(); }catch(Exception ex) { println(getSolutionFromStackoverflow(ex)) }finally { testAndApplyThefix() } fun getSolutionFromStackoverflow(val ex:Exception) { curl get stackoverflow.com?q=ex.message ... } where the developers run into an error, they immediately lookup the exception in stackoverflow.com and get the solution and validate and close the error. This is a real one that is available from drop.com The original stackoverflow blogpost is here:  https://stackoverflow.blog/2021/09/28/become-a-better-coder-with-this-one-weird-click/ Looks like these will be part of a developer toolset in the near future