Kotlin M14 is out!

Posted on by Andrey Breslav

With the release approaching, we switch to shorter milestones. Meet M14 that brings the following changes:

  • Support for annotations on file classes
  • New Java API for the Standard Library
  • operator modifier for operators
  • Backing fields are now accessed through a synthetic field variable

Language

We are wrapping up with the language changes, so nothing really dramatic has happened in M14.

NOTE: We are dropping previously deprecated features and functions, so make sure to have run Code Cleanup before you install M14.

Backing fields

The old $propertyName syntax is deprecated. To access backing fields inside getter/setter, use the field synthetic variable:

var prop: Int = 1
    get() {
        notifyRead(field)
        return field
    }
    set(v) {
        notifyWrite(field, v)
        field = v
    }

If another property in the same scope is named field, we need to qualify its usage with “this.“.

Var-properties with a backing field and a custom setter are required to be initialized upon declaration (not in the constructor), because such initializers are written to the backing field directly, bypassing the setter.

In the (probably rare) cases when this model is not flexible enough, please consider introducing backing properties (corresponding refactoring is available) or using property delegates.

Operators

As announced previously, Kotlin M14 expects functions that are called through operator notation (e.g. plus, iterator etc) to be marked with the operator modifier. Note: when we extend Any, Iterable or Comparable, operator modifiers are inherited automatically, so there’s no need to worry about them. When in need to use a Java method in the operator form, please use extension functions marked operator:

operator fun JavaClass.plus(other: JavaClass): JavaClass = this.plus(other)

Use Code Cleanup to add modifiers to all the operators used in your project automatically.

Note: Infix functions will be migrated to the same scheme in the nearest future.

Compile-time constants

Since M14 we need to prefix Kotlin constants with const to be able to use them in annotations and see as fields from Java:

const val MAX = 239

Code Cleanup will add missing const modifiers for you.

Annotate file classes

Since M13, top-level functions and properties from each source file are put into a separate class file by default (details here). Now we can annotate these classes by applying a file annotation:

// FILE: foo.kt

@file:MyClassAnnotation

package bar

fun baz() {}

will be compiled to

// Pseudo-Java
@MyClassAnnotation
public final class FooKt {
    public static void baz() {...}
}

Migration from old “package facades”

As we have transitioned to the new class-file layout, it’s time to retire the old one. Since M14 old package-facade classes (e.g. FooPackage) are deprecated, and the IDE helps you migrate your Java code to the new scheme through Code Cleanup.

NOTE: package facades will be dropped very soon, so make sure to migrate your code.

The Standard Library (previously kotlin.KotlinPackage class) is being migrated to the new scheme too: see below.

Other language changes

  • private on the top level is now private to file
  • internal is checked in the compiler (not only IDE)
  • private in interfaces is truly private now
  • equals in data classes compares arrays by calling their .equals() method (which works by identity)
  • lateinit val‘s are prohibited
  • many cases of inheritance and other degrees of freedom are prohibited for data classed (see this blog post)
  • protected and internal members are prohibited in interfaces
  • _, __, ___ are forbidden as in identifiers, i.e. we can use _foo, but not _ alone (reserved for future use)
  • identityEquals() function is deprecated in favor of ===

Standard Library changes

For the Java standpoint, Kotlin’s standard library is now organized into utility classes, each dedicated to its own data types and/or operations. For example:

  • ArraysKt — operations on arrays, extensions for arrays, array factory methods
  • CharsKt — extensions for Char and Char.Companion, most of them should be hidden
  • CollectionsKt — operations on iterables, collections and lists, list factory methods
  • ComparisonsKt — operations on comparators, comparator factory methods, and functions for performing comparisons

See more in the API docs.

IDE Changes

As usual, the IDE helps you migrate seamlessly from M13 via Code cleanup. Also there are several new handy features in M14:

  • As mentioned above, there in some cases we need private backing properties. You can easily introduce them via intention action:

  • Also you can move property initialization from constructor body or initializer block to property declaration:

  • One of the long-expected features is completion for overriding functions and properties:

  • Since M13 the IDE optimizes imports on the fly. Add unambiguous imports on the fly feature is also supported now. Give it a try:

Installation

IntelliJ IDEA 15 Public Preview has Kotlin M14 bundled, so you don’t need to install it at all.

IntelliJ IDEA 14.1 — simply update your plugin as usual.

P.S. Join our Slack channels to discuss Kotlin and your experience with it!

Comments below can no longer be edited.

31 Responses to Kotlin M14 is out!

  1. Jayson Minard says:

    October 1, 2015

    Congratulations to everyone involved in Kotlin, releases are accelerating!

    • Jayson Minard says:

      October 1, 2015

      Injekt 1.7.0 dependency injection for kotlin released (with M14 support) https://github.com/kohesive/injekt

      Jackson library with Kotlin Module will update later today
      Kovert library will update tonight
      Klutter library will update tonight

      from other authors (in the Kotlin chat on Slack):

      Kovenant library says they will also be done tonight to M14 support
      funKTionale will be updated later today
      RxKotlin tomorrow
      KotlinPrimavera this weekend

      • Jayson Minard says:

        October 1, 2015

        Kotlin-Fuel HTTP library for Android announced releasing update for M14 by tomorrow.

      • Jayson Minard says:

        October 1, 2015

        Jackson module for kotlin M14 released. Version 2.6.2-2 is now in maven central. https://github.com/FasterXML/jackson-module-kotlin

      • Jayson Minard says:

        October 2, 2015

        Klutter 0.7.0 library released for kotlin M14 https://github.com/klutter/klutter

      • Jayson Minard says:

        October 2, 2015

        Kovert 0.5.0 invisible REST framework for kotlin and Vert.x-3 released for Kotlin M14. https://github.com/kohesive/kovert

        Kovenant 2.7.0 Promises for Kotlin M14. http://kovenant.komponents.nl

      • Jayson Minard says:

        October 2, 2015

        Version 0.6_M14 of funKTionale has been released!

      • Jayson Minard says:

        October 2, 2015

        Fuel 0.55 HTTP library for Kotlin/Android is out to support M14.

  2. Roberto Gonzalez says:

    October 1, 2015

    Are these features planned for Android Studio? My Android Studio always suggest me to turn off Kotlin plugin because it is incompatible :(, I’m in the canary channel.

    • Natalia Ukhorskaya says:

      October 2, 2015

      Kotlin Plugin 0.14.449.Idea141.12 is compatible with Android Studio 1.4. What are your versions of Kotlin plugin and Android Studio?

  3. NN says:

    October 1, 2015

    Will Kotlin support implicit returns ?
    Making everything expression body gives more readable code.

    There is no reason to abandon ‘return’ completely since quiting in the middle is a useful feature, but mostly you won’t need it.

    • Andrey Breslav says:

      October 2, 2015

      Explicit returns have proven to be a very good readability aid. Also, see this discussion

      • NN says:

        October 2, 2015

        The main issue is two forms of ‘if’ .
        One that is not an expression and the other is an expression.


        fun foo() {
        if (x) f();

        if (y) g() else z();
        }

        The solution is either have an explicit ‘return’ and use same name ‘if’ for both constructions, or introduce another keyword for ‘if’ statement.


        fun foo() {
        iff(x) print("not returning");

        // Last one returns value
        if (y) g() else z();
        }

        Since many people come from Java world and not Scala, it is not an obvious one.
        For this you can have an optional return . If you don’t specify it the last expression is returned.

        Thanks.

        • Andrey Breslav says:

          October 2, 2015

          And two forms of when, and two forms of for (when it becomes an expression with yield introduced)? And we are keen on introducing control structure-like functions such as with, which would also require two forms each…

          • NN says:

            October 2, 2015

            Not exactly 🙂
            loops are expressions returning Unit, there is no need for two forms.

            The only change is making ‘if’ with mandatory ‘else’. This ensures that ‘if’-‘else’ always return a value.

            And having a shortcut for ‘if(a) b else {}’ such as ‘ifs(a) b’ .

  4. NN says:

    October 1, 2015

    What about delayed type inference ?


    var a; // a is Int according to the usage.
    ...
    if(true) a = 1; else a = 2;

    • Andrey Breslav says:

      October 2, 2015

      I don’t see so many practical use cases for the basic form of this mechanism. More advanced forms are too cumbersome and slow.

      • Christian says:

        October 2, 2015

        … especially since if is an expression in Kotlin, so you can write:

        var a = if(true) 1 else 2
        

        And then var could be val, what is even better.

      • NN says:

        October 2, 2015

        The primary use case is for generics.
        One can have


        val a = new ArrayList();
        a.add(1); // Infer ArrayList

        • Jayson Minard says:

          October 2, 2015

          one problem is that you could then a.add("d") above it and then it infers <T> to be Any which wouldn’t be what you expect and changes code without necessarily causing a compiler problem.

          • NN says:

            October 6, 2015

            Of course denoting to Any must be explicit and not implicit

        • Andrey Breslav says:

          October 2, 2015

          This is the more advanced thing I was talking about. It’s rather slow and may have very surprising results.

          • NN says:

            October 6, 2015

            It can be slow, agree.

  5. Daniel Rothmaler says:

    October 2, 2015

    Wow… that was fast 🙂

    But I have one little question regarding lateinit… Why did you introduce this in the first place? As far as I remember, you always hesitated to introduce new specialized language constructs, if they could instead be implemented in a more generic way…
    And we already have by Delegates.nonNull() for the same purpose. So why the new keyword? Is it more performant that the Delegates version? Or is it just shorter? But the Delegates version, could also be shorter, if nonNull() would be declared as top level function, doesn’t it?

    But no matter how you decide to implement it, I think there should not be two ways to do it. So if you are going to keep lateinit, you should deprecate Delegates.nonNull(); or the other way around.

    • Andrey Breslav says:

      October 6, 2015

      Delegates.nonNull() does not solve this issue, because the point is to allow frameworks to inject fields, and in the case of Delegates.notNull() the field has wrong type: NotNullVar<T> instead of T

    • Andrey Breslav says:

      October 6, 2015

      We are planning to introduce a generalization of the delegation mechanism in the future, if this project succeeds we’ll be able to retire lateinit or reduce it to the new mechanism, but it will take too long to wait for it, so we decided to introduce lateinit: it’s pragmatic, does not alter the language very much and is easy to deprecate if a better mechanism comes around.

  6. Jon Renner says:

    October 3, 2015

    has the “it” reference in anonymous function syntax been changed?

    I mean like this:

    myArray forEach {
    println(it.name)
    }

    • Jayson Minard says:

      October 3, 2015

      No… Sometimes people see it as an error when their plugin is out of sync with the Kotlin stdlib used in a project and it can’t read the library, therefore it doesn’t understand forEach and therefore doesn’t know it should be in use.

      Are you asking because you have this problem?

  7. Krtko says:

    October 3, 2015

    Any word on inlined constants? For me it’s a pretty essential feature.

    • Andrey Breslav says:

      October 6, 2015

      This issue requires some more work, probably won’t be part of 1.0

      • Krtko says:

        October 12, 2015

        Ah that’s disappointing. Well I hope it doesn’t get abandoned all together. I really rely heavily on constants and having them inlined during compile time helps performance.