Hi, Habr! We hope in the foreseeable future to get to Kotlin. Past this article (February) could not pass.
We read and comment!
I just finished reading
Bruce Tate’s book “
Seven Languages ​​in Seven Weeks ” - and since then I have loved it! Although, I have experience with most of the languages ​​described in the book, I really liked how the author characterizes languages, and how these characteristics ultimately affect the practical use of the language.
That's why I decided to write another additional chapter for this book. She will be devoted to a language that I know well enough, I understand its advantages and disadvantages: this is Kotlin.
')
The purpose of this article is not to teach you Kotlin language, but to show its character. Do not try to understand it thoroughly. It is better to pay attention to how the features described here could affect your programming style.The most typical feature of Kotlin is that this language, in essence, does not introduce anything that would not be found in other programming languages. The fact is that Kotlin uses all these old finds in the most masterpiece way. Remember the superhero of Iron Man. Tony Stark has assembled Iron Man from the simplest electronic components. Iron Man does not have such superpowers as Superman or Flash. This may seem weak, but in the long run this is a huge advantage. Let's talk about it below, but for now let's start with the basics.

The basics
It is believed that Kotlin is intended for programming in one or another IDE - for example, in IDEA IntelliJ, Android Studio or CLion (Kotlin / Native). Here we start with the command line to demonstrate Kotlin in a simpler context. After
installing Kotlin , run the REPL (interactive shell) like this:

Let's try with numbers:
>>> 1 1 >>> 1 + 2 3 >>> 1.0 + 2 3.0
Simple math works. This is Kotlin / JVM running on a Java virtual machine. Integers in Java are primitives. And in Kotlin? Let's check the type of the number:
>>> 1::class class kotlin.Int >>> 1.0::class class kotlin.Double
Both are objects! In general, in Kotlin all entities are objects. What about java? Kotlin is fully interoperable with Java, but we see that the above types are Kotlin types. The fact is that some of the Kotlin built-in types cover Java types. You can see what type of Java will be in this case, using the
java
property of
Class
or the
javaClass
property of any object:
>>> 1.0::class.java double >>> 1.0.javaClass double
This is a
double
! Double precision numbers (double) in Java are primitives. How is this possible? Kotlin uses optimization to apply primitives instead of objects when no object-oriented features are used. This happens under the hood, absolutely does not concern the developer. If we need to use
double
as an object, then
Double
will go instead. From the point of view of the developer, one can still say that “everything is an object”. We define several properties:
>>> val a = 1
This property is read only. You can also define a property for reading and writing with
var
:
>>> var a = 1
Please note: the type is not listed here. However, do not be fooled by this: Kotlin is a language with strong static typing. The property type is simply inferred from the type of the value assigned:
>>> ::a.returnType kotlin.Int
Enough math, let's move on to more interesting possibilities.
Security
The iron man was constructed because neither the police nor the army could rescue Tony Stark from the captivity of the terrorists. Tony made Iron Man to take care of his own safety, as well as expand his capabilities. He also became famous for this.
Similarly, JetBrains created Kotlin. The same company creates the most popular integrated development environments. All their tools were originally created in Java, but the JetBrains team in practice felt all the flaws of this language. Then the company began to experiment with other languages, for example, Scala or Groovy, but they did not satisfy them either. Therefore, in the end, JetBrains decided to create their own language, with an eye to the fact that this new language should provide maximum security (so that no errors occur in the products) and scalability. In addition, Kotlin excellent propiaril JetBrains. They were already known all over the world, and when a community of experts emerged who decided to use their funky language, JetBrains became even better for them. (Here I have just told the story in the most general terms. If you are interested in details, listen to
this podcast ).
Kotlin significantly outperforms Java in terms of security. Properties must be initialized:
>>> var a: String error: property must be initialized or be abstract
By default, types are not nullable:
>>> var a: String = null error: null can not be a value of a non-null type String
If we want to show that this type is zeroed out, is this done with the help of
?
:
>>> var a: String? = null
True, nullable types cannot be explicitly used:
>>> a.length error: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
Nullable types are similar to others, such as the optional types used in Scala. Before use, this type must be unpacked. You can use a safe call that acts exactly as a normal call if the property is not
null
. If the property is
null
, then we do not call the method, but simply return
null
:
>>> a = null >>> a?.length null >>> a = "AAA" >>> a?.length 3
We can also use an unsafe call that will throw an exception if the property is zero;
>>> a = null >>> a!!.length kotlin.KotlinNullPointerException
Working with unsafe calls is not recommended, so resorting to them is necessary only if absolutely necessary. In projects at Kotlin, they are very rare. This is a huge difference between Kotlin and Java, where all calls are unsafe.
Intellectuality
Iron Man is so cool because his battle suit is truly intelligent. He calculates the situation and warns Tony about the dangers. Kotlin is also truly intelligent, and thus helps developers a lot.
One of the models of such intellectuality is clever type conversion. When we check if a property is not zero, we can use it as if it is really non-zero. To demonstrate some more advanced features, we will work with files. I suggest to use IDEA IntelliJ (
here it is told how to get to work with it). Alternatively, you can try all these features in the
online REPL . Consider an example:
fun smartCastingExample(str: String?) { if(str != null) print("Length is " + str.length) }
As you can see, str is used explicitly (without unsafe or secure calls). That's why in the
if(str != null)
check scope, the type is from
String?
to
String
. Also, everything will work if we exit the function with the opposite check:
fun smartCastingExample(str: String?) { if(str == null) return print("Length is " + str.length) }
The principle works not only with nullability. A clever type casting is also possible:
fun smartCastingExample(any: Any?) { if(any is String) print("String with length " + any.length) }
Kotlin is well supported in IDEA IntelliJ, Android Studio or CLion. In these IDEs you will get a ton of tips, tips and support. Here is an example where imperative handling of a collection, typical of Java, is replaced with the declarative, intrinsic to Kotlin. Please note that it is the development environment that offers and performs the entire transition:

Minimalism
Tony Stark does not don the entire Iron Man if he does not need it. Usually he uses only the machine or some small components.

The philosophy of Kotlin, in particular, postulates that the simple must remain simple. Here is the Hello World code on Kotlin:
fun main(args: Array<String>) { print("Hello, World") }
This is just one function that outputs text. Other typical operations on Kotlin are also simple. When we don’t need the whole function body, we can do with a single expression:
fun add(a: Int, b: Int) = a + b
Below you will see more than once the exact same minimalistic style.
Flexibility
Iron Man loses to Superman in some important ways. For example, laser eyes are given to Superman from birth, he can incinerate the enemy with a look when he pleases. Tony Stark did not equip Iron Man with eye lasers - perhaps because he did not see any urgent need for it. It is important to note here that he could easily have added such a feature to Iron Man. In fact, it can be done by any user of Iron Man. But, at the same time, on Iron Man, you can hang other upgrades, which may well be no less effective, but they will be cheaper. This is a huge potential for flexibility. Let's go to practice. In most programming languages, literals of collections are provided in one form or another. In Python, Ruby or Haskell, the list can be defined like this:
[1,2,3]
. Kotlin has no such collection literals, but it provides top-level functions (those that can be used everywhere), and the standard Kotlin library has such top-level functions with which you can create collections:
>>> listOf(1,2,3) [1, 2, 3] >>> setOf(1,2,3) [1, 2, 3] >>> mapOf(1 to "A", 2 to "B", 3 to "C") {1=A, 2=B, 3=C}
Why is this so important? When a collection literal is provided in the language, it also defines how the user will apply the collections. All collections have some characteristics. There is an extensive discussion about which lists are better - changeable or immutable? Modifiable is more efficient, but immutable is much more thread-safe. On this occasion, there are many opinions and arguments. With this in mind, would you like the list literal to generate exactly a mutable, or just an immutable list? In any case, you will somehow impose on the programmer options for using the language, since the programmer will prefer to use the collections literal. Kotlin in this case leaves freedom of choice.
listOf
,
setOf
and
mapOf
give immutable collections:
>>> var list = listOf(1,2,3) >>> list.add(4) error: unresolved reference: add list.add(4) ^ >>> list + 4 [1, 2, 3, 4]
Although it is not difficult to create a mutable collection with
mutableListOf
,
mutableSetOf
and
mutableMapOf
:
>>> mutableListOf(1,2,3) [1, 2, 3] >>> mutableSetOf(1,2,3) [1, 2, 3] >>> mutableMapOf(1 to "A", 2 to "B", 3 to "C") {1=A, 2=B, 3=C}
Pay attention: anyone can define their own collection, and then the top-level function that will create it:
fun <T> specialListOf(vararg a: T): SpecialList<T> {
Above it is easy to see that I used the generalized parameter of type
T
Do not worry. This means that you need to transfer a set of similar elements to create a collection of this type.
Due to the fact that Kotlin uses basic capabilities, rather than embedded literals, third-party libraries do not inferior to its standard library when working with Kotlin. Another great feature that greatly democratizes libraries and unleashes developers is the so-called extension function. The point is this: you can define such a function so that it acts as a method:
>>> fun Int.double() = this * 2 >>> 2.double() 4
Please note: in practice, no methods are added to the class. Extension functions are simply functions that are called in such a special way. This feature may seem simple, but it is really powerful. For example, in Kotlin, as in other modern languages, functions are provided for handling collections:
class Person(val name: String, val surname: String) val avengers = listOf( Person("Tony", "Stark"), Person("Steve", "Rogers"), Person("Bruce", "Banner"), Person("Thor", "") ) val list = avengers .filter { it.surname.isNotBlank() } .sortedWith(compareBy({ it.surname }, { it.name })) .joinToString { "${it.name} ${it.surname}" } print(list)
A huge advantage of Kotlin is that such and similar functions are defined as extension functions. For example, take a look at the
filter
implementation:
inline fun <T> Iterable<T>.filter( predicate: (T) -> Boolean ): List<T> { return filterTo(ArrayList<T>(), predicate) } inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterTo( destination: C, predicate: (T) -> Boolean ): C { for (element in this) if (predicate(element)) destination.add(element) return destination }
If it is not worth implementing, you can define this function yourself. If you need any other function for processing collections, you can easily define it. Often, developers do this. For example, you can find a lot of libraries, which define the extension functions for Android. They simplify development for Android. Another result of this decision - at your service there is just a lot of methods for processing collections.
Here it is also important to note that
filter
is a function that extends not the
List
type, but the
Iterable
interface:
public interface Iterable<out T> { public operator fun iterator(): Iterator<T> }
You can easily define your collection class that implements
Iterable
, and the language will add these methods to it for you to handle collections. Even
String
implements it. That is why you can use all methods of processing collections with
String
:
>>> "I like cake!".map { it.toLowerCase() }.filter { it in 'a'..'z' }.joinToString(separator = "") ilikecake

Brief summary
Tony Stark was not born a superhero, and no radioactive spider bites him. He constructed the Iron Man through his incredible knowledge and experience. Similarly, JetBrains is a company that creates great IDEs for different languages; her people learned a lot from this job and embodied their knowledge by writing an incredible programming language. They didn’t bring anything new to the world of programming, but simply suggested an ideally crafted language that uses the advantages of many other programming languages ​​- that’s why it’s where maximum developer productivity and the highest quality of projects are achieved.
A great example of such clever design is the Kotlin tuples. When the language still existed in beta, tuples were already supported in it. Although, when the Kotlin team analyzed how exactly work with tuples affects program design, it turned out that their influence was not always positive. That is why the tuples were not included in the release. Instead, in Kotlin you can use the
data
annotation. It is more universal, and the Kotlin developers had no doubt that, in general, it will positively affect the work with the language. Tuples are still being discussed and, perhaps, someday native support for them will appear in Kotlin. However, for this to happen, the Kotlin team and the developer community must be convinced of the appropriateness of such a solution.
This eloquently characterizes Kotlin. This is not a hodgepodge of ideas, but a truly well-made language. It contains a minimal set of the most powerful features, which together give you awesome features. In general, Kotlin leaves you with much more freedom, including for co-creation.
Home reading
If you want to learn more about Kotlin, I recommend reading the
documentation of the language , as well as get acquainted with the resource
Kotlin Koans . If you are interested in Kotlin for Android, look at
this book .