Kotlin: first impressions

Georgiy Shur
Ackee
Published in
9 min readNov 14, 2016

I’m planning to constantly update and extend this post the first couple of months I’m working with Kotlin. I will write down the things that I like in Kotlin, the things I miss or don’t like and the things I’m still not sure about. These things may even change their “baskets” as I’ll be gaining more experience with this language :).

Moreover, any discussion and critics are welcome, as I’m just starting to learn Kotlin, some things may be different in reality than they seem to me now.

The things I like in Kotlin

1. Extension functions

Extension functions are basically more intuitive and less boilerplate util methods. They are declared as the functions belonging to some particular class (attention: they aren’t really the member functions of this class, more on this later). They may be defined anywhere (in some util file or even as a member function of another class).

And yes, you may access class fields (properties in Kotlin) and functions from extension functions without the instance reference.

Extension functions are called the same way as member functions:

But be careful, they aren’t member functions and don’t modify the class in any way. So, they could not override the member functions, and the subclasses of the receiver class cannot override these functions as member functions (but they can be overridden as extension function with subclass as the receiver).

Apart from extension functions, extension properties may be used too, but with some limitations. As they aren’t really members of extended class, the may not be initialized. and the getters/setters should be defined explicitly. So, they are basically the same extension functions with shorter notation.

Extension functions are resolved statically, which means that if you have two extension functions for class and subclass with the same name, the one for the type which was declared will always be called (MyClass in this example):

So, if you were thinking that this is some magic, it is just sugar, but really sweet sugar. Just imagine how much functions you may add to the common classes that you aren’t able to modify. For example, Kotlin already uses some in Collections or Android Extensions. You may add any functions you want to any existing class and call them as they are really inside. It appears more logical and drastically reduces the boilerplate code.

Some other extensions usage ideas occurred to me that may be combined with other technologies.

Firstly, the annotation processing (or any code generators) may become more powerful with the help of extensions. It will be quite easy to generate some access methods for existing class that are using another generated class. We’re planning to try this approach in our library and will share the results ASAP.

The second usage is extending of Observable class for RxKotlin. The creation of new Rx operators in now so easy with the help of extension functions. Just a little example:

What you can achieve with it is limited by your imagination only.

How are you using the Kotlin extensions? Feel free to write in comments or to me directly.

2. Functions overloading and default parameters

This is the thing that I really hate in Java. For example I want to create a new instance of a fragment. But depending on the place from which I’m creating this instance, I need to pass zero, one or more arguments. Sometimes some of those argument sets overlap, sometimes they don’t. So, I need to create more newInstance() methods, pass nulls as some arguments (which isn’t readable at all) or use some smarter patterns like Builder (which produces even more boilerplate code).

Remember the old lovely query() method from SQLite?

I remember when I was writing my own wrapper for query I had more than ten overloaded methods.

In Kotlin you may forget about overloading in that sense. You may define the function only once with all arguments, define the default values and call just the ones you need.

Moreover, if you need to pass more arguments than just first, you may use so-called named arguments.

It is really intuitive, readable and saves you a lot of code.

It is good practice to use named arguments for multi-argument functions even if it is optional, because the programmer may immediately see what is getting passed on without going to the function declaration.

3. Data classes

All of us spend some time writing model classes — POJOs for data entities. Nowadays there exist multiple generators, plugins and tools that simplify this boilerplate code writing, but still, it feels like these classes may be written with less lines of code…

But sometimes we need more constructors, custom equals() and hashCode() and maybe some copying mechanism.

In Kotlin, it’ll look like this:

Yes, all properties, getters and setters are generated and may be accessed in the short form. The constructor is overloaded the same way as functions in Kotlin. It means that in this example, the first three arguments are mandatory, so they should be provided, but other are optional.

Moreover, the next methods are automatically generated based on the properties:

  • toString()
  • equals() and hashCode()
  • copy() (which may be called with altered parameters)
  • componentX() functions (destructuring declarations)

Although data classes have some limitations (data classes cannot be open, sealed or inner and cannot extend other classes), they are a great replacement for old clumsy POJOs and save us some time.

The things I’m still not sure about

1. Null safety

Well, I feel like I’m almost ready to move null safety to the things I like in Kotlin, but there are a couple of issues I’d like to write about.

Firstly, for you who doesn’t know what null safety in Kotlin is, I’ll try to explain shortly.

In Kotlin, it is clear already on the declaration level if the variable can be null. By default, the variables aren’t nullable. But with the sign “?”, you may say to the compiler that the variable can be null.

So basically we are living now on two different planets.

The first one is perfectly safe, we can forget about NullPointerException, null checks and other things like this, because the compiler won’t allow us to make these errors. Bot on the other side, we may forget about nulls as well, all our objects no always should have some values, which isn’t convenient sometimes.

The second one, the planet “?”, isn’t so safe, as the objects on it may carry the null values. But still, it is safer then the Java planet, because if you’re trying to invoke some function on the variable marked with “?” (nullable), the compiler won’t allow it, because this call isn’t safe. The call should be marked with “?” too, and basically it works as our favorite null check in Java. If the object is null, the function just won’t be called.

But it doesn’t mean that you should live on one planet only, these approaches may (and will) be combined depending on your needs. But here comes the most difficult part. The inhabitants of these two planets don’t get along well together. The people from the safe planet just won’t accept the “?” guys just like that. But here comes the really cool thing that I like in Kotlin null safety — Elvis operator.

Moreover, the right part of the Elvis operator may be an expression or even a block of code.

The most important thing I see here, that when in Java, you may just add the null check anywhere you want, Kotlin applications are more demanding on the design level. But if you design your classes, objects and functions properly from the beginning, Kotlin will award you with more readable and concise code, absence of NPEs and will save you much time on debug. But if the design was poor, the refactoring and the usage of code may be even more hard and time-consuming.

The planet “?” has its dark side, the “!!” part. When using “!!”, you may just ignore all the safety mechanisms provided by Kotlin an write your code in Java style.

Personally I saw that people overuse “!!” in Kotlin. Maybe there are some situations where there is no other options, but I haven’t ever been in a need to use unsafe calls. I think it’s just a matter of habit to start to think Kotlin way instead of Java and plan your code to be safe from the beginning. Anyway, I’m quite happy that this operator exists, because I think that safety should be enforced by warnings rather than by prohibitions.

There are some other cool implications from Kotlin null safety, for example safe casts.

2. UI in Anko DSL

Never heard or read about an Android developer who is moving to Kotlin and not trying Anko. Anko is a DSL for creating layouts written in Kotlin from the guys who wrote Kotlin, allowing to forget about XML layouts and create UI dynamically in Kotlin :).

I think it’s the biggest change for me concerning Kotlin and it deserves a separate post (that will be here someday!). My colleague has recently started his own series of posts about Anko tips and tricks and I recommend to read it too.

But still, I’ll try to briefly share my opinion about the benefits and drawbacks of this approach.

Pros:

  • Performance (there is a great article about Anko vs XML performance, you should read it)
  • Easier code generation (IDE is working more smoothly with Kotlin than with XML)
  • Logic in layout creation (now we may write any initialization code and call any methods in the creation blocks)
  • Remove some boilerplate (no need to write “match_parent”/”wrap_content” if they’re default, and I don’t use Butterknife anymore since we can reference created views straight from the code)

Cons:

  • Lack of documentation and tutorials (it’s quite annoying because there is a lot of features and they aren’t so intuitive to understand)
  • Styling and theming arent’t totally well-thought-out
  • Compatibility problems with libraries that are based on LayoutInflater and XML view creation (for example Calligraphy)
  • Bad type safety (in nested constructs it is quite easy to mess with different lparams functions and end up with type cast exceptions that are tricky to track… I did it a lot of times)

Anyway I’m happy with Anko and I don’t want to use XML anymore. I hope that this project will be constantly improving and It’ll be the next thing I like in Kotlin.

The things I don’t like in Kotlin

1. Generics

There are some issues with Kotlin generics. I’ve tried to rewrite some old Java code with a lot of generics, but in the end I understood, that it isn’t possible.

The first problem is that Kotlin doesn’t support raw types. Yes, of course raw types is a big breach in type safety and one should be careful with their using an avoid them if possible. But on the other hand, if used properly, they may be useful.

Suppose we’re trying to implement MVP pattern in some simple library.

Now, the concrete implementation for some screen.

As you can see, on the one side, it is a big potential safety breach. If the user doesn’t implement the same view interface as this concrete presenter has as its generic type, the app will crash.

But on the other side, if I can enforce the user somehow to implement the proper view with its presenter (maybe by some compile-time checking or by combining the documentation with proper runtime exceptions or by some other means), this raw type usage may be quite safe and allows me to avoid some redundant boilerplate code (as passing view type as the generics).

But in Kotlin, I can’t write that. Even if I’ll add the view type as the second generic type, I can’t avoid unchecked conversion when calling delegate.attach(this).

So, even if you don’t have potential unchecked casts but have some nested generics, the code is becoming really unreadable when you need to define all these generics explicitly.

The other thing is so-called variance, the replacement of Java wildcards. It is described in detail in Kotlin reference. I believe it is very logical and makes sense, but it is just so unintuitive. I fought with Kotlin generics for three days and got a grasp on how this variance works. But even now I’m a little confused from time to time with declaration and use-site cases. Java wildcards in contrast gave perfect sense after the first usage. The big advantage of Kotlin is its relative simplicity and practicality, and these covariants and contravariants just seem so academic and don’t fit this notion.

I agree that type-safety is a big thing for generics and it should be enforced, but through warnings and hints, not through restrictions reducing the possibilities.

--

--

Georgiy Shur
Ackee
Writer for

I work as a senior Android developer in Ackee. Trying to follow the new trends in my field and occasionally share my experience with others.