More Deprecations Coming

There are two more items on the language cleanup list: backing-field syntax and static type assertion operator.

Backing Fields

When you have a property and you don’t implement at least one of its accessors (get or set) manually, such a property gets a backing field, i.e. a piece of storage holding its value:

you can access the backing field through the name of the property prefixed with the $ sign:

This may be needed to bypass the custom accessor(s).

This feature is rather rarely used, and also clashes visually with string templates ("$foo", surprisingly, has nothing to do with backing fields), so we want to get rid of it.

In case you really need it, your workaround is backing property:

Since no getters or setters are generated for private properties, the resulting byte code will be exactly the same.

Static Type Assertions

Another rarely used feature is the following syntax:

The type after colon in an expression specifies the expected static type of it, i.e. this is not a cast, but simply an instruction to the compiler to make sure that the static type of this expression is actually “Bar”. The fact that it’s hard to explain has something to do with this being rarely used (I think Kotlin’s test data is the only major client). So, we are withdrawing this syntax, and maybe will make use of it later (possibilities include array/list slices and C-style ternary conditionals).

In case you needed this syntax to disambiguate your overloads, as is a good workaround.

About Andrey Breslav

Andrey is the lead language designer of Kotlin at JetBrains.
This entry was posted in Language design. Bookmark the permalink.

19 Responses to More Deprecations Coming

  1. What happens to this example?

    var counter = 0 // the initializer value is written directly to the backing field
    set(value) {
    if (value >= 0)
    $counter = value
    }

    • I suppose it becomes:

      private var _counter = 0
      var counter = 0
      set(value) {
      if (value >= 0)
      _counter = value
      }
      get() = _counter

        • Sergey Ryabov says:

          Looks very unnatural. And this double initialization also adds ambiguity. But the main point is this need to override both-or-none accessors. Can’t we just stick to the “underscore-prefixed” convention instead of “dollar-prefixed”? After all noone should use underscore-prefix for usual private vars as per Kotlin Code Conventions.

        • Damian Petla says:

          This change require more lines of code, I don’t like it. In my case I combine Dagger 2 with Kotlin and I use very often something like this

          var typeface: Typeface? = null
          [Inject] set([Named("bold")] value) {
          $typeface = value
          }

  2. Olivier Binda says:

    Thanks for the recent blog posts giving us news/insights about kotlin progress and workarounds/explanations on how to adapt our code : it helps.

  3. Nick says:

    If null : Foo is going away, and we’re supposed to use “as” to resolve overload ambiguity, there is a “no cast necessary” warning that will need to be removed.

    someOverloadedFunction(null : Foo) // Warning: no cast needed. You can use ‘:’ if you need to cast to a super type.

  4. ac says:

    So you are add back all the boilerplate you supported to remove? nice.

  5. Amal Samally says:

    Please, don’t remove syntax for backing field access! Feature is very useful.
    Backing properties are really ugly and produce hundreds lines of boilerplate. It’s better to remove such use cases (like effective lazy initialized properties as for now), not creating new.

    • Could you share your use cases where backing fields save you “hundreds lines of boilerplate”?

      P.S. Lazily initialized properties are supported through Delegates.lazy() and Delegates.notNull().

  6. Denis says:

    Данный механизм уберать не надо. Удобен в случае когда нужно сделать проверку значения и/или нотификаию изменения. Делегаты в этом плане добавляют ненужный код или сильно замусоривают его.
    например:
    имеем
    var a:int=0
    set(value){
    //проверки частные для этого поля, не сказать что это используется на каждом шагу, но далеко не редкость, а это именно тот случай который будет страдать более всего
    $a=value
    //события, могут быть общими могут быть частными
    }
    отказ приведет к :
    private _a:int=0 // лишняя строка (абсолютно логичная может быть автоматизирована и автоматизирована сейчас, замет отказываться?) которых хватает и от которых хотелось бы избавиться
    var a:int=0
    get()=_a // лишняя строка (абсолютно логичная может быть автоматизирована и автоматизирована сейчас, замет отказываться?) которых хватает и от которых хотелось бы избавиться
    set(value){
    //проверки частные для этого поля, не сказать что это используется на каждом шагу, но далеко не редкость, а это именно тот случайкоторый будет страдать более всего
    _a=value
    //события, могут быть общими могут быть частными
    }

    если же через делегаты выражать и убрать бэкхранение то это превратиться что то наподобие
    var a:int=MyDelegate(aa->{//лямбда условий
    }, (aa,name)->{//лямбда генерации событий
    }
    + делегат должен хранить значение -> на одно поле создаем класс
    или + объявить
    private _a:int=0 // лишняя строка (абсолютно логичная может быть автоматизирована и автоматизирована сейчас, замет отказываться?) которых хватает и от которых хотелось бы избавиться
    и сослаться на нее в делегате…

    в общем те мелочи которые привлекают удалять не нужно и это одна из таких больших удобных и правильных мелочей.

  7. Anton Rutkevich says:

    Thanks for announcing upcoming Kotlin features before implementing them, Andrey!

    I must be missing something extremely obvious, but the backing field feature seems to be extremely useful.

    First, how will the constructor syntax work without backing fields?

    public class Customer(val id: Long = -1,
    val name: String = "",
    val age: Int = -1,
    val birth: String = "") {
    }

    Senond, what will happen to model objects?
    As for now, the Customer class above can be used as the model class for Gson
    Will the model for the Customer class above transform into something like this?


    import com.google.gson.annotations.SerializedName

    public class Customer() {

    }

    My only assumption is that you meant “we will remove ‘$backingField’ syntax for custom property setter & getter” instead of “we will completely remove the backing field feature”.

    So, will syntax like


    // 1
    public class Customer(val id: Long = -1) {
    }

    // 2
    public class Customer(val id: Long = -1) {
    public var name: String = ""
    }

    stay?

  8. After Googling for “Kotlin no cast needed” I happened on this page and this sounds relevant to my problem.

    I was able to boil down a compilation error in my code to the following minimal form to reproduce the problem.

    Use of either ‘:’ annotation (line with val x …) or ‘as’ cast (line with val y…) suffice as workarounds to get around what seems to be a Kotlin compiler bug at the last line (line with val z…)

    If you can verify that this is a bug then I’ll leave it to you to file the bug report. I hope this info is useful. Look forward your comments.

    Cheers

  9. Bother. I just copy/pasted the raw code & didn’t do character entity escapes for the angle brackets in the generic declarations. Appears the HTML form entry filtered them out as invalid markup tags.

    Free free to email if you would like the original code.

    Cheers Justin

Comments are closed.