Constuctors in Kotlin


#1

I think hat the thing with the primary constructor directly in the class header is a good idea. The class code becomes compact and easy to read.

But. I’m not that happy with the “anonymous initializers” you must use if you have a more complicated constructor need. My quibble is with the anonymous part. I dont think the code reads that well when there are just a couple of curly braces that indicates that this code is part of the constructor. I would like to have som keyword or something. Like

class Example(param: Int) {


  val property = param


  contructor initializer {
          // some code

  }


  fun doSomething() {
          // some method code
  }



}


#2

While doing the morning dishes I realised I can restate my problem with this as: I have a problem curly braces that means more than just "here comes a block of code", but instead means something like here is an class initializer or something. If there are more meaning than "here is a code block" I would like to see it expressed somehow in the language.


#3

Thanks for this trick:

  contructor initialize {           // some code   }

I didn't know about this and this solves a lot my problems I had to understand how instance initialization is supposed to work. Maybe it's an idea to add this "constructor myInitMethod" thing to the Kotlin docs. It wasn't clear to me from reading through http://confluence.jetbrains.net/display/Kotlin/Classes+and+Inheritance

/Oliver


#4

I think you misunderstood me. The code I wrote was how I, personally, would like to see that the code should be written. It is not how it works.


#5

Surprise, surprise: the code below compiles and prints "1 2":

open class Foo(param1 : Int, param2: Int?) {   var value1 = param1   var value2 = param2;

  constructor initialize {
  if(value2 == null)
           value2 = value1 * 2
  }

  public fun print() {
  print(value1)
  print(" ")
  print(value2)
  }
}

fun main(args : Array<String>)
{
  val foo = Foo(1, null)
  foo.print()
}


Apparently, the constructor expression does not need to have a name. It compiles and produces the same output in case you just write

constructor {
     if(value2 == null)
          value2 = value1 * 2
}

You can have several constructors, but only the first one will be considered. The code below prints “1 3”.

open class Foo(param1 : Int, param2: Int?) {   var value1 = param1   var value2 = param2;

  constructor {
  if(value2 == null)
           value2 = value1 * 3
  }

  constructor {
  if(value2 == null)
           value2 = value1 * 2
  }

  public fun print() {
  print(value1)
  print(" ")
  print(value2)
  }
}


Seems like there is no point in having several constructors and the compiler should flag it.

Regards, Oliver


#6

This is a bug in the compiler: annotations on anonymous initializers are not checked. What you thought was a name is actually an annotation (syntactically).

You can have several constructors, but only the first one will be considered. The code below prints "1 3".

Both of your "constructors" are executed sequentially, the second one has no effect, as value2 is no longer null.

Thanks for the report. I filed it in the tracker: http://youtrack.jetbrains.com/issue/KT-2208


#7

Both of your "constructors" are executed sequentially, the second one has no effect, as value2 is no longer null.

Of course, stupid me ;-). I like the approach with the constructor block. There is only one way to initialize the instance. Having several constructor methods as in C++/Java make things only more complicated as you have several possible combinations to take care of that all must initialize cleanly. In Smalltalk you would initialize the instance as in the sample code before in this post like this:

MyClass.new: param1 with: param2      ^super new           param1: param1;           param2: param2;           initialize

With new:with: being a class method:

| myObject | myObject := MyClass new: 123 with: null; yourself.

The approach with the constructor block in Kotlin is just as elegant and simple although there is no message passing and no cascaded messages at your disposal. Nice. What also would be cool, is something like this:

val = Foo.new(123, null)

To me this is "more object-oriented" (aka a message being sent to an object). Never really understood why saving the new method/keyword as in Scala is considered that much of a gain.