owned this note
owned this note
Published
Linked with GitHub
# Kotlin
Kotlin is something programmers never forget about. I hadn’t heard of Kotlin until 17 June this year. Since then, I have used almost no other language.
The story started a few weeks before that date. By a coincidence, I was in contact with Lenka Kucerova, passionate CEO & Co-founder of StarLift.org, who sent me a link to a hackathon that would take place in Prague. I didn’t know much about hackathons, but as always, I wanted at least to make an attempt to attend. My friends and I built a nice-looking PDF application that we sent them. Luckily we got in, the hackathon going to be our first experience of its kind.
How does it all relate to Kotlin? Because at [HackPrague](hackprague.com), the hackathon, there was a sponsored prize called *Let's Program in Kotlin!* encouraging us to utilize the new-born language. Honestly, my first impression was: What a terrible language must it be that they need to reward people for using it? From what I heard, it’s trying to be innovative, while interoperable with good old Java. Of course, we had no time learning the new language during the hurried event full of hustle. Instead, we opted for *The most innovative UX for mobile event discovery* prize. Eventually, we got 2nd place and won the prize.
One week later, motivated, we attended another hackathon in Prague. The second day of coding we realized that our concept is not a winning one. We wanted to include a snippet of innovation in our project that would at least make us feel we have something that others do not. I really don’t know why, but my following commit on Github included a few classes written in Kotlin. (Side note: It didn’t help to succeed.)
What is important, I had a slight scent of what Kotlin may be and that perhaps it’s not as bad as I thought at first. My following weekend wasn’t as full as my weekends tend to be and I had some time I could invest into learning more about Kotlin, so I opened the Kotlin language reference and started reading. It turned out to be a life-changing weekend (from the programmer’s part of life :)). The more I read, the more strongly I was captivated.
Let’s dive into it. I’ll briefly present only a few features I like the most. The purpose of the article is to motivate you to learn Kotlin, definitely not to serve as a language reference.
## Not a boring language
Java programmers benefit a lot from having everything declared with a type that is known during compile time. The drawback is writing a *boring* parts code, i.e. things a monkey could write being given only the line of code, without even knowing the context.
```java
String s = "Hello World!";
BufferedStreamReader bsr = new BufferedStreamReader(stream);
```
In Kotlin, the same can be achieved without boring code. Kotlin developers consider type declarations, `new` keyword and semicolons as boring, hence the equivalent in Kotlin is
```kotlin
val s = "Hello World!"
val bsr = BufferedStreamReader(stream)
```
Of course, you can override the inferred type, or provide it in case it can't be inferred.
```kotlin
val pet: Animal = Dog()
val pet2 = Dog() as Animal // downcasting or upcasting
```
Whenever you specify `val`, the variable is final. For rewritable variables use `var`.
## Null safety
In Kotlin, every type either can hold null values (`String?`) or can’t (`String`). Assign a possibly null value to a variable not accepting null values and the compiler will complain. Neither invoking a method on a nullable type is permitted. So how do we sort it out? All the following examples produce the same result.
```kotlin
// This is basically what one would write in Java style
fun whoIs(user: User?): String? {
if (user != null) {
return user.name
} else {
return null
}
}
// But the `if` block is also an expression in Kotlin
fun whoIs(user: User?): String? {
return if (user != null) user.name else null
}
// The ?. operator will invoke the method only if the object is not null,
// otherwise the whole expression evaluates to null
fun whoIs(user: User?): String? {
return user?.name
}
// Finally, using a short syntax of methods (the inferred return type is still String?)
fun whoIs(user: User?) = user?.name
// We can supply default values with the Elvis operator ?: that will evaluate
// to the right side if and only if the expression on the left is null
// Note that in this particular case, the compiler infers the return type to by non-null `String`
fun whoIs(user: User?) = user?.name ?: "no one"
```
## Extension functions
Some languages support extending existing classes by defining their members (fields or methods) without changing the class definitions at all. Libraries tend to define many extension functions on common objects and the methods eventually collide since a class can't have two methods with the same signature. However, Kotlin has everything covered.
First, it's important to understand how Kotlin's extension functions work and how they can be compiled to Java. Consider the following definition:
```kotlin
fun Boolean.thenRun(block: () -> Unit): Boolean {
if (this) {
block.invoke()
}
return this
}
```
The method has one argument, a lambda without parameters that returns `Unit` (equivalent to `void` in Java). If the receiver of the function (i.e. the boolean value) is true, the lambda is invoked. After that, the original boolean value is returned.
Let's save the code to `MyFile.kt`, compile it and decompile the resulting `MyFileKt.class` back to Java. The output is roughly the following (I removed unimportant parts):
```java
public final class MyFileKt {
public static final boolean thenRun(boolean $receiver, @NotNull Function0 block) {
Intrinsics.checkParameterIsNotNull(block, "block");
if($receiver) {
block.invoke();
}
return $receiver;
}
}
```
As we can see, Kotlin tackles the problem by defining a public static method instead that takes the boolean value as its first argument. Amazing! We can have as many libraries as we want and member collision will not occur since you always need to import the right one.
Few notes here:
+ Kotlin's type `Boolean` changed to `boolean` as the compiler knows that it won't hold null values
+ We defined the method directly in the file, not as a class member, however, Kotlin supports also extension functions as class members.
+ As you may have noticed, things in Kotlin are usually `public` and `final` unless other is specified.
Now consider what use may this function have. Look at the following logic written in Java:
```java
public class MyClass {
...
public boolean doSomething() {
boolean isSuccess = doTheTask(); // returns true on success
if (isSuccess) {
System.out.println("OK");
}
return isSuccess;
}
}
```
Pretty simple. We run a task, store its result. If positive, we run another block of code (printing to console in this case). Then we return the original value. Now look at what Kotlin offers:
```kotlin
fun doSomething(): Boolean {
return doTheTask().thenRun {
println("OK")
}
}
// or even better
fun doSomething() = doTheTask().thenRun { println("OK") }
```
Not only is the code much shorter, we completely got rid of a variable!
Note that if the last argument of a function is a lambda, you can put it out of parentheses, and you can omit them if the parentheses are empty. Kotlin has many extension functions built in that you don't have to write.
## No boilerplate code
Code in Kotlin:
```kotlin
data class Human(var name: String?, private val birth: Date) : Mammal(birth)
```
Code decompiled to Java is the following. It's longer, I removed more uninteresting parts.
```java
public final class Human extends Mammal {
@Nullable
private String name;
private final Date birth;
public Human(@Nullable String name, @NotNull Date birth) {
Intrinsics.checkParameterIsNotNull(birth, "birth");
super(birth);
this.name = name;
this.birth = birth;
}
@Nullable
public final String getName() {
return this.name;
}
public final void setName(@Nullable String var1) {
this.name = var1;
}
@Nullable
public final String component1() {
return this.name;
}
private final Date component2() {
return this.birth;
}
@NotNull
public final Human copy(@Nullable String name, @NotNull Date birth) {
Intrinsics.checkParameterIsNotNull(birth, "birth");
return new Human(name, birth);
}
public String toString() {
return "Human(name=" + this.name + ", birth=" + this.birth + ")";
}
public int hashCode() {
return (this.name != null?this.name.hashCode():0) * 31 + (this.birth != null?this.birth.hashCode():0);
}
public boolean equals(Object var1) {
if(this != var1) {
if(var1 instanceof Human) {
Human var2 = (Human)var1;
if(Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.birth, var2.birth)) {
return true;
}
}
return false;
} else {
return true;
}
}
}
```
I guess you get my point that Kotlin is concise. Much more concise.
## Properties & Delegated properties
Whenever there are `getSomething()` and `setSomething(value)` methods, Kotlin considers it to be a property and you can access it just by writing `obj.something` and `obj.something = value`. When you create a class with a property (such as the following example), it is compiled to a class with private property with appropriate getters and setters. This is exactly what happened in the previous example. Of course one can modify everything.
```kotlin
open class HeyWorld(val abc: String) { // not final class
// `abc` is a constructor argument and an immutable property with a setter
var foo = "bar" // public getter and setter
private val now = Date() // private getter and no setter (because of `val`)
protected var amount: Int? = null // protected property initialized to null
// here we define custom getter; field is a special keyword in this scope
get() = field ?: 0 // returns the value if not null, otherwise returns 0
private set // setter is private
open var abracadabra: Boolean? = true // not final field (unlike the rest)
set(value) { // value is of type Boolean?
field = if (value != null)
// but we negate it as it has been smart-casted to Boolean
!value
else null
// the same could be achieved by writing
// field = value?.not()
}
}
```
A delegated property means that you delegate the responsibility of accepting and providing value to someone else.
```kotlin
class Example {
var p: String by Delegate()
}
```
The `Delegate` object must have some `getValue` and `setValue` methods defined, but let's focus on the usability again.
```kotlin
// lazy evaluation
val lazyValue by lazy {
print("The property is being evaluated for the first time!")
"Hello World!"
}
// managing more properties by one object
class Person(val map: MutableMap<String, Any?>) {
var name: String by map
var age: Int by map
}
```
## Conclusion
Kotlin has many features I present as magic. What struck me at the beginning was to realize that everything is compilable to Java and therefore must abide with its *restrictions*. And indeed, every bit of magic here has an explanation.
There are many things left unexplained in the article and you may be wondering if the language really can work as expected and if there are any drawbacks. Well, you can either read the docs yourself or trust me saying it's amazing. Good luck and happy coding!
* [Kotlin Reference](https://kotlinlang.org/docs/reference/)
* [The best features of Kotlin!](https://android.jlelse.eu/kotlin-best-features-a3facac4d6fd)
* [Ten Kotlin Features To Boost Android Development](https://www.toptal.com/android/kotlin-boost-android-development)
<!--
Safer (null safety)
• Clear code (syntax, properties)
+ Less of code (boilerplate code)
• Encourages better code design
• Extension functions (many predefined functions)
• Any (objects, primitive types, Unit, Nothing)
• Lambdas, functional programming
• Properties (accessing properties, getters/setters)
• Delegated properties
• Data class
• Expressions with when, if
• Infix operators
• Destructing classes
• Singleton objects
• No more findViewById
• Ranges
• Operator overloading
• Type-Safe builders
• Many more
-->