Kotlin M14 is out!
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 fileinternal
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
andinternal
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!
Jayson Minard says:
October 1, 2015Congratulations to everyone involved in Kotlin, releases are accelerating!
Jayson Minard says:
October 1, 2015Injekt 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, 2015Kotlin-Fuel HTTP library for Android announced releasing update for M14 by tomorrow.
Jayson Minard says:
October 1, 2015Jackson 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, 2015Klutter 0.7.0 library released for kotlin M14 https://github.com/klutter/klutter
Jayson Minard says:
October 2, 2015Kovert 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, 2015Version 0.6_M14 of funKTionale has been released!
Jayson Minard says:
October 2, 2015Fuel 0.55 HTTP library for Kotlin/Android is out to support M14.
Roberto Gonzalez says:
October 1, 2015Are 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, 2015Kotlin Plugin 0.14.449.Idea141.12 is compatible with Android Studio 1.4. What are your versions of Kotlin plugin and Android Studio?
NN says:
October 1, 2015Will 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, 2015Explicit returns have proven to be a very good readability aid. Also, see this discussion
NN says:
October 2, 2015The 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, 2015And two forms of
when
, and two forms offor
(when it becomes an expression withyield
introduced)? And we are keen on introducing control structure-like functions such aswith
, which would also require two forms each…NN says:
October 2, 2015Not 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’ .
NN says:
October 1, 2015What 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, 2015I 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:
And then
var
could beval
, what is even better.NN says:
October 2, 2015The primary use case is for generics.
One can have
val a = new ArrayList();
a.add(1); // Infer ArrayList
Jayson Minard says:
October 2, 2015one problem is that you could then
a.add("d")
above it and then it infers<T>
to beAny
which wouldn’t be what you expect and changes code without necessarily causing a compiler problem.NN says:
October 6, 2015Of course denoting to Any must be explicit and not implicit
Andrey Breslav says:
October 2, 2015This is the more advanced thing I was talking about. It’s rather slow and may have very surprising results.
NN says:
October 6, 2015It can be slow, agree.
Daniel Rothmaler says:
October 2, 2015Wow… 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, ifnonNull()
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 deprecateDelegates.nonNull()
; or the other way around.Andrey Breslav says:
October 6, 2015Delegates.nonNull()
does not solve this issue, because the point is to allow frameworks to inject fields, and in the case ofDelegates.notNull()
the field has wrong type:NotNullVar<T>
instead ofT
Andrey Breslav says:
October 6, 2015We 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 introducelateinit
: it’s pragmatic, does not alter the language very much and is easy to deprecate if a better mechanism comes around.Jon Renner says:
October 3, 2015has the “it” reference in anonymous function syntax been changed?
I mean like this:
myArray forEach {
println(it.name)
}
Jayson Minard says:
October 3, 2015No… 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 knowit
should be in use.Are you asking because you have this problem?
Krtko says:
October 3, 2015Any word on inlined constants? For me it’s a pretty essential feature.
Andrey Breslav says:
October 6, 2015This issue requires some more work, probably won’t be part of 1.0
Krtko says:
October 12, 2015Ah 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.