Kotlin M5.3: IntelliJ IDEA 13, Delegated Properties and more

Kotlin M5.3 brings support for IntelliJ IDEA 13 and some new features for you to check out. We are moving towards powerful runtime support, including reflection and other framework-enabling features. This milestone marks our first steps in that direction.

IntelliJ IDEA 12.1 and 13

First early access versions of IntelliJ IDEA 13 are coming out, and we ship a Kotlin plugin compatible with these versions. Remember it’s an EAP, use it at your own risk. Of course, good old IntelliJ IDEA 12.1 is supported as well.

Note: Some news about Kotlin support in Android Studio are coming soon.

Many Improvements

As usual M5.3 brings many improvements both in the compiler and the IDE. In the compiler we are still mostly concerned with performance, which is gradually improving. The IDE gets new quick fixes and refactorings, some of which are described below. You can now navigate to properties overriding the one you are looking at (see icons in the left gutter). The editor recognizes the syntax of KDoc (thanks to this pull request)… But first, let’s talk about cool new language features, some long awaited, some unexpected (maybe).

New Language Feature: Delegated Properties

We often get feature requests like:

  • Support lazy properties: the value gets computed only upon first access.
  • Support observable properties: listeners get notified about changes to this property.
  • Support storing properties in a map, not in separate field each.
  • Support <my favorite kind of property semantics>…

One way of addressing these requests would be to say that life is tough and users have to suffer. Another way would be to support different kinds of properties on the language level. We do not like either of these approaches: too many unhappy users on the one hand, too many ad hoc features on the other hand. So, we take a third approach: support a unified mechanism that covers all these requests (and probably more), so that particular kinds of properties can be implemented in libraries, without altering the language.

Meet delegated properties:

There’s some new syntax: you can say “val <property name>: <Type> by <expression>”. The expression after by is the delegate, because get() and set() methods corresponding to the property will be delegated to it.  Property delegates don’t have to implement any interface, but they have to provide methods named get() and set() to be called. For example:

When we read from p, the get() function from Delegate is called, so that its first parameter is the object we read p from and the second parameter holds a description of p itself (e.g. you can take its name). For example:

This prints “Example@33a17727, thank you for delegating ‘p’ to me!” Similarly, when we assign to p, the set() function is called. The first two parameters are the same, and the third hold the value being assigned:

This prints “NEW has been assigned to ‘p’ in Example@33a17727″.

Probably, you already see how to implement things like lazy or observable with this mechanism. Try it as a metter of exercise, but most of it is already done in the standard library.

The kotlin.properties.Delegates object holds the most useful stuff. Let’s start with lazy:

Delegates.lazy() is a function that returns a delegate that implements a lazy property: the first call to get() executes the lambda expression passed to lazy() as an argument and remembers the result, subsequent calls to get() simply return the remembered result. If you want thread safety, use blockingLazy() instead: it guarantees that the values will be computed only in one thread, and that all threads will see the same value.

Now, let’s turn to observable:

The observable() function takes two arguments: initial value and a handler for modifications. The handler gets called every time we assign to ‘name’, it has three parameters: a property being assigned to, the old value and the new one. If you want to be able to ‘veto’ the assignment, use vetoable() instead of observable().

Next may be somewhat unexpected: users frequently ask what to do when you have a non-null var, but you don’t have an appropriate value to assign to it in constructor (i.e. it must be assigned later)? You can’t have an uninitialized non-abstract property in Kotlin:

You could initialize it with null, bit then you’d have to check every time you access it. Now you have a delegate to handle this:

If you read from this property before writing to it, it throws an exception, after the first assignment it works as expected.

The last thing to show is properties stored in a map. This comes up a lot in applications like parsing JSON or doing other “dynamic” stuff:

In this example, the constructor takes a map:

Delegates take values from this map (by the string keys – names of properties):

Of course, you can have var’s as well (with mapVar() function), that will modify the map upon assignment (note that you’d need MutableMap instead of read-only Map).

There are other use cases, and probably numerous improvements to these ones. Fantasize, experiment, enjoy! ;)

First Steps in SAM Conversions

We introduced SAM constructors last time. Of course, this is not enough, so we are working on full SAM conversions. The feature is not finished yet, but you can already use it in simple case like this:

To remind you, SAM conversions is what Java 8 uses for lambdas: when you have an interface with only one (abstract) method, like Comparator or Runnable, you are allowed to pass in a lambda where an instance of this interface is expected (in this example we pass a lambda instead of a Runnable). Kotlin does not have this as a language feature (for it is not needed in a language with proper function types), so it will only work for Java classes.

First Steps in “Callable References”

Another thing we are working on is “Callable References” or “Feature Literals”, i.e. an ability to pass named functions or properties as values. Users often ask “I have a foo() function, how do I pass it as an argument?”. The answer is: “you prefix it with a ‘::’”. For example:

Here “::isOdd” is a value of function type “(Int) -> Boolean”, and you can pass it as a filtering predicate. Another example:

This function return a composition of two functions passed to it: compose(f, g) = f(g(*)). Now, you can apply it to callable references:

If you want to use a member of a class, you need to qualify it, and the result will be of type “extension function”,  e.g. String::toCharArray gives you an extension function for type String.

Note that this is early work in progress, so many things do not work yet, for example, overload disambiguation, type inference, support for properties etc. Eventually this feature will evolve into full type-safe reflection, but today we are only starting working on it.

Change Signature Refactoring

Adding/removing/reordering function parameters may be tedious when you have a lot of call sites to update. That’s why IDEs prove a “Change Signature” refactoring. Place your cursor on a function or a constructor and hit Ctrl+F6 (Cmd+F6 on Mac), and you’ll get a dialog like this:

Change type, rename, reorder or delete parameters and all your call sites will be updates accordingly.

Quick Fixes for “Type Mismatch” etc

Thanks to contributions by Jack Zhou, Michał SapalskiWojciech Łopata and other students of Open Source Mentorship program led by Stanford University, we now get many cool quick fixes. For example, when you get a type mismatch error, hit Alt+Enter and get some proposals to fix your code:

Code Transformations

Another group of useful IDE actions to convert between equivalent forms of code, like:

You can also use Ctrl+Shift+Up/Down to move statements or declarations:

Installation

As usual, the new plugin can be installed from our plugin repository.

Have a nice Kotlin!

About Andrey Breslav

Andrey is the lead language designer working on Project Kotlin at JetBrains. He also works on making the Java language better, serving as a Java Community Process expert in a group for JSR-335 ("Project Lambda"), and occasionally speak at software conferences such as Devoxx or JavaOne.
This entry was posted in General and tagged . Bookmark the permalink.

28 Responses to Kotlin M5.3: IntelliJ IDEA 13, Delegated Properties and more

  1. B7W says:

    Realy surprised, delegated properties realy cool!

    Why only name convention (get, set), why not interface? In for loop statment it is a necessary step to support the old java code. But here we do not need it.

    • What we don’t need is an interface. Why introduce harder conventions when required?

      • B7W says:

        - Find all implementation, learn language with IDE
        - Less thing to remember and type, just ask IDE to override methods
        - Api, easy to understand that it is property not some other things

        And I can ask same question, why introduced ReadOnlyProperty and ReadWriteProperty traits? Maybe because it is comfortably and clear in strongly typed system.

        • As you see, those interfaces exist, they are just not mandatory. They are introduced to encapsulate implementations.

        • Robert says:

          Also +1 for mandatory interfaces.
          If declaring delegates via interface you tell the reader explicitly what the get/set methods are about.
          Especially you are telling the reader that this is a DelegateProperty class.

      • Jan Kotek says:

        +1 for mandatory Delegate interface. Kotlin is strongly typed language and should behave as such. I take simple naming convention for simple stuff like operators or loops. But Delegate already has complex signature and bunch of classes extending it.

      • Ron says:

        This immediately jumped at me, too. Delegated properties are really cool, but dispatching based on method names rather than a generic interface is strange, unexpected and inconsistent.

        • Inconsistent with what?

          • Cedric Beust says:

            Inconsistent with the rest of the language: this kind of ad hoc polymorphism is not available anywhere else in Kotlin.

            I agree with the other commenters, I find resorting to ad hoc polymorphism (à la Go) quite surprising and counter intuitive. Either make it available everywhere or nowhere.

          • It is available everywhere else in Kotlin: this is how for loop works (we could require Iterable), and operator overloading (we could require Addable, Subtractable etc), and multi-declarations (we could require Record 2, Record 3 etc). Having an interface for property delegates would be inconsistent with all that.

          • lacroix1547 says:

            I hope you forgive us if we are maybe too easily scared by loosing “@Override” and “implements” on any code fulfilling a well defined role.

          • Mario Arias says:

            If the interfaces (traits) exists but aren’t mandatory, you could satisfy both groups.

            IMHO the functions signature are long, and you could get benefits from using a interface to ensure the right signature (and to navigate).

            But as Andrey said there are other uses of this conventions in Kotlin, for example, calling “invoke” member functions using just “()” or the array-like accessors: “foo[1] = Bar()”

            You could just establish the convention of using the aforementioned interfaces/traits in your code even if aren’t mandatories (For example, I use square brackets around non-kotlin annotations just for clarification and aesthetics)

      • lacroix1547 says:

        +1 for mandatory Delegate interface, or it smells like grails.

  2. pilgr says:

    So tasty features! Mmm..

  3. Dody Gunawinata says:

    The delegated properties is definitely a nice surprise :) This is awesome.

  4. lacroix1547 says:

    I needed to use different reference holder classes in java to do things like those delegates.
    They really didnt feel natural, writting getters and setters was a pain.

  5. Stephen Colebourne says:

    Delegated properties look good. They remind me of an idea I’ve wanted to see explored in a language, which I saw as method inheritance, which we could refer to as delegated methods. The concept would be that a method could be wrapped by a function. This would allow behaviour like “once” where the result of invoking a method on an object is could be cached.

    fun Int calculate(Int input) : Once {
    // do complex calculation
    }

    (note that I’m using Java’s layout for types as it makes more sense in general, and more sense when a method can “extend” a delegate/prototype as the syntax matches class inheritance).

    Other example uses might be LogEntryExit or Timer. Another way to think of it is inline AOP. BTW, Fantom has a “once” keyword which this idea is a variation of.

  6. Juha Komulainen says:

    Is it possible to access the delegate object directly?

    I was thinking about creating a delegate which would function like a normal mutable variable, but would store the maximum and minimum value that the variable has contained in addition to the current value. It seems that I need to do something like this:

    val levelRange = RangeDelegate(42)
    val level: Int by levelRange

    val max = levelRange.maximum

    That’s not bad for a single case, but it’s somewhat annoying duplication if there are 10 properties that I’d like to track.

    Since the $field -syntax is not used with delegates, perhaps that could be used to access the underlying delegate-object directly like the following?

    val level: Int by RangeDelegate(42)

    val max = $level.maximum

  7. Jon Nichols says:

    Is there a way to get the type of the property from my delegate? PropertyMetadata only has the name and not the type (including if it is read only or read-write). I know that can be passed by the caller but it seems like useful information (especially for my delegate that would like to be more generic).

    • This is not supported for now, as there’s no API to represent Kotlin types at runtime. We are working on reflection, and when it’s ready, PropertyMetadata will expose a lot more than now: type, owner class, visibility, annotations etc.

  8. Daniel Alves says:

    \o/ The delegated property is really a cool feature.

    I started to use it with JavaFx Observables and it works perfectly!

    About the callable references, it will work like in C# where a instance method delegated is always the same instance? Or it will follow the scala’s and java’s way to create a new object of type Func for each time that I used it?

    I, personally, prefer the first option, so we can emulate the C# delegate events and not only this, it is more easy to register and unregister handlers when developing UI components.

  9. Andrew says:

    > Kotlin does not have this as a language feature (for it is not needed in a language with proper function types), so it will only work for Java classes.

    Actually, SAM conversions for Kotlin classes can be useful, because while there are function types in Kotlin, you can’t, for example, define extension method for function type. Now if I want to use extension methods for functions in my package, I have to define a trait with single abstract method and implement methods in that trait (or use extension methods).

    P.S.: API documentation for Kotlin has lots of broken links, for example http://jetbrains.github.io/kotlin/versions/snapshot/apidocs/kotlin/concurrent/package-summary.html has link to http://jetbrains.github.io/kotlin/versions/snapshot/apidocs/jet/String.html, which responds with 404

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">