DEV Community

golanir
golanir

Posted on

Kotlin 101

Kotlin is a (relatively) new statically typed language developed by Jetbrains, IntelliJ idea anyone?

Open-sourced at 2011 and Kotlin 1.0 released on February 15th 2016.
although widely used by JetBrains developers, Kotlin's big break was on Google I/O 2017 where Kotlin was announced as an official language for android development.

Some of Kotlin's key features are:
Concise, Safe, Interoperable & mature.

Kotlin is 100% interoperable with Java and you can use it with your current project without any problems, you can call Java code from Kotlin and vice versa, all you need to do is add a small plugin and you're all set.

Kotlin adds lots of modern features that organizations stuck with Java 7 or 8 or Android developers surely miss and one of its big advantages is that it solves the nullability problem.

Kotlin has a place in any of today's development environments, Kotlin/JVM for Android, backend & everything else that runs on the JVM, Kotlin/JS for frontend developers and Kotlin/Native for iOS, MacOS, Windows, Linux, WebAssembly & Android (again).

let's dive right in

VARIABLES

in Kotlin we declare variables like this:

val is a read only (immutable) variable that we must initialize at declaration and we can't change its value.

val name: String = "nir"

The compiler is smart enough to infer the type and we can declare it like this

val name = "nir"

var is a mutable variable

var lastName: String = "golan"

As in val we can remove the type and our code will run just fine

var lastName = "golan"

Variables declared with the var keyword can be change at a later time

lastName = "golanster"

but we can't change the type, so:

lastName = 123

will not compile.

CLASSES

Classes in kotlin are declared with the class keyword

class Person constructor(val firstName: String, var lastName: String)

As in the variable declaration where we could omit the type, here we can omit the constructor

class Person (val firstName: String, var lastName: String)

When we use the val keyword in the constructor, we declare and assign the class properties.

Another important class keyword is data, when we add the data keyword in front of the class we get getters, setters (for var and not for val) & toString, hashCode, equals & copy overrides.

Object & Class Instantiation

In Kotlin we instantiate objects & classes like this:

val person = Person("nir", "golan")

Notice we don't use the new keyword

Functions

Functions in Kotlin are declared with the fun keyword

fun sum(first: Int, second: Int) {}

If the function have a return value we add the return type after the ()

fun sum(first: Int, second: Int): Int {}

and in the {} we define the body of the function

if & when

In kotlin if & when are expressions and have a return value, so in our function we can write

fun sum(first: Int, second: Int): Int {
    if (first > second) {
        first
    } else {
        second
    }
}

In Kotlin we also have default values & named parameters in functions

fun sum(first: Int = 5, second: Int = 10): Int {
    if (first > second) {
        first
    } else {
        second
    }
}

We can call the function like this:

val number = sum(5,10) //normal call
val number = sum(first = 5, second = 10) //named parameters
val number = sum(second = 5, first = 10) //with named parameters we can
                                         //call them in any order we want
val number = sum(second = 22) //with default values we can omit
                              //any parameter and call just the one we need

And because Kotlin is a concise language we can omit some {} and get this

fun sum(first: Int, second: Int) = if (first > second) first else second

And this is the closest thing we have to a ternary operator in Kotlin.

In Kotlin when is a switch statement on steroids, it can be used as a normal switch statement, but because it's also an expression that returns a value when used like that, we must add an else clause

fun whatAmI(value: Any?) = when(value) {
    3 -> "value is exactly 3"
    is Int -> "double the value = ${value * 2}"
    "What the fuck?" -> "Swich case + if statement!"
    else -> "No value"
}

In Kotlin everything inherits from Any, just like Object in Java

In the above use case we evaluate value, we declare the value of value and based on the value of value we return the value :-)

Extension Function

We can extend any Kotlin class with a function of our own, in fact, Kotlin itself is an Extension functions over Java.

Let's take Int for example

fun Int.maxValue(other: Int) = if (this > other) this else other

Here we define an extension function for Int where we pass in another value and return the bigger one

val max = 3.maxValue(4) // returns 4

We can add the keyword infix in front of the function thus making the syntax a bit more friendly

infix fun Int.maxValue(other: Int) = if (this > other) this else other
val max = 3 maxValue 4

Null Safty

First, let's see how NPE or null pointer exception can happen in Java

String luckyNumber = "7";
System.out.println(luckyNumber.length());
luckyNumber = null;
System.out.println(luckyNumber.length());

Here, when our program will reach the last line it will throw a java.lang.NullPointerException, now lets see how Kotlin can help us with it.
In Kotlin a variable can't be null, if we declare a variable like we did before

var name: String = null

our program will not compile and we will get this message: null can not be a value of a non-null type String

In order for us to use null in Kotlin we must declare a support for null in the type

var name: String? = null

The ? in the end of the type tells the compiler that name can be null, if in the declaration we omit the type the compiler will infer the type as String?

When using nullable variables we have safe & unsafe ways to deal with them.
First, let's take a look at the safe way,

name?.length()

The ? will check if the variable is null or not and only if its not null will execute the length() method

name!!.length()

With !! we're telling the compiler: "I know this can be null, trust me, i know what i'm doing".
I don't have to tell you that this is the best way to get a NullPointerException, right?

If we need to have a value returned even if the variable is null, we can use the elvis operator, which returns what's right of it if the left side is null

val res = name?.length() ?: 0

Collections

In Kotlin we have all the basic collections: list, array, map, set, hashMap, hashSet, etc..
Lets see some ways we can manipulate them.

val list = 1..100 // declaration of a list with the numbers 1 to 100

list.map { it * 2 } //map iterates over the list and **it**
                    //is the value currently being evaluated
    .filter { v -> v % 2 == 0 } //filter out the results that are odd

Now let's say that we have a list of 1000000000000000 elements, this could take time even on the latest system, and for the sake of the argument let's say we need to pass the list to a web page for it to display.
We can't let the user wait several minutes until they see some info on the screen, this is where asSequence comes in

val list = 1..1999999999999900

list.asSequence
    .map { it * 2 }
    .filter { v -> v % 2 == 0 }

list.forEach{print(it)} //extension function that iterate over the list
                        //and print the current value

asSequence evaluates the list as lazy and every time a new value is added it's being printed.

That's all for now, Kotlin is a very exciting language with many more topics to cover and i will add more in the next few days.
Happy coding.

Top comments (0)