Hello, Kotlin!

Sathya Bandara
5 min readJan 30, 2022

--

Image Credits: unsplash.com

I was working as a java software engineer for more than 4 years. Recently I joined a firm that uses Kotlin instead of Java and I have been learning Kotlin for the past few weeks.

Learning Kotlin has been fun and interesting. Also, I feel it is fairly easy for a Java developer to learn Kotlin because the syntax is almost similar but Kotlin is less verbose than Java. From my post, I want to share with you some cool features I learned about Kotlin.

Background

Kotlin is an open-source, statically-typed programming language that features both object-oriented and functional programming paradigms. It is the primary development language in Android.

Now let’s dive into some unique features in Kotlin.

Single Type System

A type system is a set of rules that determine the types of a programming language construct.

Kotlin comes along with a very powerful typing system. Unlike Java, Kotlin does not have primitive types. Hence, Kotlin’s type system is solely on objects.

Following are the built-in types in Kotlin.

Image Credits: https://speakerdeck.com/npryce/the-kotlin-type-hierarchy-from-top-to-bottom?slide=9

Other than above, users can define their own types by means of Classes, Interfaces, Enums.

Type Inference

Kotlin is a strongly typed language that supports Type Inference. Kotlin compiler can automatically identify the data type of the variable or the return-type of a function even if you don’t explicitly specify it.

For example, in Kotlin you can declare a variable in 2 ways.

  1. var num : Int = 2
  2. var num = 2

Note that in the second method, you didn’t have to specify the type of the variable because Kotlin is able to infer the type based on the value assigned to the variable.

This is the same case for the return type of functions.

Smart Casts

Kotlin compiler can perform type casts automatically in the following cases.

  • Casting from a supertype to a subtype
val object: Any = "test string"
if(object is String) {
// Here, object is automatically casted to String sub-type.
println(object.length)
}
  • Casting from nullable types to their non-nullable counterpart
var firstName: String? = "test string"
if(firstName != null) { // Smart cast.
print(firstName.length)
}

Null safety

In Kotlin, types are non-null by default. To allow a variable to hold null, we can declare a variable with the nullable operator (?).

var firstName: String = null // This will give compilation errorvar firstName: String? = null // Ok

Now, Kotlin compiler will warn us whenever we try to access variables declared as nullable.

Elvis Operator

The Elvis operator (?:) is designed specifically to handle null cases. It will return a non-null value or a default value when the variable is null.

val name = firstName ?: "Empty"

You can also throw an exception if the variable is null.

val name = firstName ?: throw Exception("Invalid name")

Top-level Functions & Variables

Top-level functions are functions inside a Kotlin package that are defined outside of any class, object, or interface definition. These functions can be invoked directly, without the reference to a class or an object. Top-level variables are the same as top-level functions. Variables are defined outside a class definition in Kotlin.

fun main() { 
println("Hello, Kotlin!")
}

In Kotlin, variables are of two types.

  • Read-Only
    val the keyword is used for read-only variables. This is similar to the final keyword in Java meaning the variable cannot be reassigned once initialized.
  • Mutable
    var the keyword is used for mutable variables in Kotlin. When a variable is defined as var, it is possible to re-assign its value in a latter part of the code.

Single Expression Definitions

Kotlin gives us the capability to define functions as a single expression for direct operations. Basically, a single-expression function is a function where a single expression is assigned to the function, and the expression’s evaluated value is returned when this function is called.

fun getGreeting() = "Hello, Kotlin"

The above is a single expression function that takes no arguments and return “Hello, Kotlin” string whenever it is called.

String Templates

String templates in Kotlin are String literals that can contain embedded expressions.

val message = "Hello $variable"

Unlike in Java, a String template can contain logic as well.

val message = "Hello, ${if(variable != null) variable else "Unknown"}"

Named Arguments

Kotlin allows you to specify the names of arguments that you’re passing to the function. This can be helpful when a function has many arguments.

fun fun_name(name1: data_type, name2: data_type )

Default Arguments

you can provide default values to parameters in the function definition. When invoking the function, you can omit passing arguments if they are not different from the default ones.

fun printGreeting(greeting:String = "Hello", name:String ="Kotlin") {
println("$greeting, $name")
}

This allows to configure and re-use functions and objects by leveraging these default and named arguments syntax.

Companion Objects

In the scenario where you do not want to give direct access to the instantiation of a particular class, you can define a companion object inside that class. By declaring a companion object, you can access the properties and functions of the original class using the class name without instantiation. This is useful when implementing the factory design pattern in Kotlin.

class CompanionClass {

companion object CompanionObject {

}
}
val object = CompanionClass.CompanionObject

Data classes

Data classes are defined for the purpose of holding data. The Kotlin compiler automatically generates the following functions for them.

  • toString()
  • equals()
  • hashCode()
  • copy()
  • componentN()

Example of a data class declaration.

data class Employee (
val id: String,
val name: String?
)

Extensions

Kotlin provides the ability to extend a class with new functionality without having to inherit from the class. You can extend functions as well as properties of a class.

This is highly useful when you want to incorporate new functions/properties for a class from a third-party library that you cannot modify.

For extending properties, initializers cannot be used. You have to override the getters/setters of those properties. You can also define new properties for existing classes.

Higher-Order Functions

A higher-order function is a function that takes functions as parameters or returns a function. By default, Kotlin functions are first-class. First-class functions can be stored in variables and data structures and can be passed as arguments to and returned from other higher-order functions.

Function Types

In Kotlin, function types are used to store functions as variables. An example is shown below.

val greet = fun() { println("Hello, Kotlin!") }

I hope you got a high-level overview of some of the useful features of Kotlin. For detailed information please refer the official Kotlin documentation. Thank you for reading!

--

--

Sathya Bandara
Sathya Bandara

Written by Sathya Bandara

A Software Engineer on a Quest for Knowledge, Eager to Learn, Share, and Lift Others Along the Way

Responses (1)