Photo by Joel Filipe on Unsplash

One of the key features that made me evaluate Kotlin as a substitute language for Android development was the conciseness of the language. With the interoperability being the main reason since I tried with Scala a few years ago until I finally surrendered.

I’ve always felt that Java (5–7) has been to chatty. It’s fairly hard to write beautiful code both in terms of how it performs and how it appears. The latter is not important until the first one is fulfilled, but still.

And during my first three years of Kotlin development I’ve found new perks along the way and thought I might share a few of them now. This will be the first part of a undetermined number of posts about this (for the mere fact that I’m too lazy to write it all at once).

First out is the obvious data classes, it seems to be the first line of fire when convincing someone to try Kotlin. So let’s be on our way.

Data Classes

data class Person(val name:String, val age:Int)

This little snippet gives us a final class with two immutable public properties. (If you call this class from Java you’ll see two get-functions. getName() and getAge()). If you for some reason want to have mutable properties then use the var keyword instead of val and you alter it after creation.

You do also get a good toString() method describing the class name, all properties by name and their values, equals() and hash() functions that are properly used to check for equality between instances. I. e. they generate an equality check for all properties in the constructor. By now we have a java bean class generated for us.

But it gets better, we get a copy-method to copy the class into a new instance, and since we all only use immutable and thread-safe classes this is the only way to have an instance like val bob = Person("Bob", 33) ever get older is to copy him with a new age. And thanks to that you can call a function with named parameters in kotlin, and that you can have default values in a function, the copy-function becomes really nice to use. If you just call it without any values you’ll get a straight copy that will equal the copied one. And if you want a copy except for one value like in our case, you can call it like this val olderBob = bob.copy(age = 34) and we have a much wiser, smarter and more experienced copy of Bob. And it doesn’t matter how many properties you have, as long as you name them you can use them in any order as you wish.

The last little neat thing about data classes is that they support deconstructing (again for the constructor properties). Here you do have to know the order of the parameters in order to get the correct ones. val (name,age) = bob now you have two values; name and age that you can use freely without bob.

I don’t know if you noticed but I actually sneaked in kotlin features in the end instead of data class features. And thats the beauty I see after using Kotlin for a while. It’s not the particular features by them selves that are elegant, it’s the combination of a lot of small smart features.

Delegates

Let’s jump into the next one, delegates. Let’s say you heed to the statement “composition over inheritance”, then you should like this. Also the rule of inheritance in many languages is that you can only inherit from one class, then the class delegation is very handy. Let’s be concrete, I want do create a FavoriteModule that dispatches events every time a favorite is added or removed from it, i.e. implements a Dispatcher. Instead of inherit from an implementation of the Dispatcher I want to compose my class with such an implementation. I can choose many different ways of doing this, a private property in my class that I expose or injecting it into the constructor and expose that instead. I prefer the latter since it gives me more flexibility over my compositions and it’s a lot easier to test. But when doing any of these I need to write delegation functions that only forwards the call to the composed functionality. But using class delegation I don’t have to any more.

class FavoriteModule(dispatcher:Dispatcher):Dispatcher by dispatcher

This snippet does exactly that, it generates all delegation functions for the Dispatcher interface to call the dispatcher instead. Without the need of any boiler plate code from my side. The magic keyword for delegation is by.

And for all of you that rather would extend a Dispatcher then delegate it, what happens when you need to extend the BaseModule too? Then you would benefit from it too.

class FavoriteModule(
dispatcher:Dispatcher
):BaseModule, Dispatcher by dispatcher

Type aliases

Type alias is just as you might guess. Aliases for types to better match your specific domain. Or to make your code more self explanatory, or elegant.

Imagine this code.. it’s clear what it does, but it’s not clear why.

when(value) {
is Int -> if(value in 2..5) pass()
is Char -> if(value in 'a'..'d') pass()
)

But if we change it like this, it should be very clear, very domain specific and one might argue, more elegant. The result in the end is the exact same code.

typealias NumericalGrade = Int
typealias AlphabeticalGrade = Char
when(value) {
is NumericalGrade -> if(value in 2..5) pass()
is AlphabeticalGrade -> if(value in 'a'..'d') pass()
)

And if you have a strange third variant of grade (like I had when I was young) you can also benefit from the comma separated or in when statements/expressions.

typealias NumericalGrade = Int
typealias AlphabeticalGrade = Char
when(value) {
is NumericalGrade -> if(value in 2..5) pass()
is AlphabeticalGrade -> if(value in 'a'..'d') pass()
"G", "VG", "MVG" -> pass()
)

This is again not type alias but a mix of nice kotlin features. And to be honest, if the context was clear from the code around I would simplify the when statement and not use type aliases at all. I would probably have the following code snippet. But that didn’t help me describe type aliases…

when(grade) {
in 2..5 -> pass()
in 'a'..'d' -> pass()
"G", "VG", "MVG" -> pass()
)

Another type alias thing that I can’t really decide on at the moment is when adding extension functions to type aliases. It’s great for descriptiveness and domain specific code, but since the extension function isn’t enforced on the type alias (but to the actual type under it) I have mixed feelings towards using it.

Let’s look at an example, we want to convert Radians to Degrees (back and forth). The underlying type for both of these are Double’s in this example.

typealias Degree = Double
typealias Radian = Double
fun Degree.toRadian(): Radian = this / 180 x Math.PI
fun Radian.toDegree(): Degree = this × 180° / Math.PI

The problem here is that I can call myRadian.toRadian() and get something I didn’t expect. But when reading the code (when it’s used correctly) it is very clear and descriptive in my opinion.

fun getSectorArea(centralAngle: Radian, radius: Double): Number {
return (centralAngle.toDegree()/360) * Math.PI * radius.pow(2)
}

I realize that it might seem like I don’t like type aliases, but I do. But I might as well share my doubts on it’s usage. Just to put them back on the positive side. Here are two samples where I would definitely use them:

// When being more descriptive in calls that can be misinterpreted.
typealias
Degree = Double
typealias Radian = Double
fun convert(angle: Degree): Radian
// When handling function types like lambdas
typealias Lambda<T> = () -> T
fun doOnComplete(action: Lambda<Int>)

Until next time
→ Bob

Lead Developer at Qvik, Coach, Agile Thinker, GDG Lead.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store