Constructors

As with Java and Ruby, a Kotlin class does not necessarily need an explicitly-declared constructor. By default, you get a zero-parameter constructor, as Foo did in the preceding examples. Many of your Kotlin classes will not need any custom constructors… but a few will need one, and on occasion they might need more than one.

What You Normally See

In Java and Ruby, declaring constructors is a matter of having a specific method (or thing that looks like a method) declared on the class. In Java, that pseudo-method has the name of the class:

class Foo {
  final private int count;

  Foo(int count) {
    this.count = count;
  }
}

while in Ruby, we use the initialize method:

class Foo
  def initialize(count)
    @count = count
  end
end

Similarly, JavaScript uses a function named after the class, at least in some approaches of implementing objects in JavaScript.

The way you will normally see Kotlin classes have a constructor is by making the actual class name itself take the constructor parameters:

class Foo(var count: Int) {
  fun something() {
    count += 1
    println("something() was called $count times")
  }
}

fun main() {
  val foo = Foo(0)

  foo.something()
  foo.something()
  foo.something()

  println("the final count was ${foo.count}")
}

Here, we have one constructor parameter, count. The var keyword in front of it means that we can use it like a var property, in this case changing its value via the increment (+=) operator.

The Formal Approach

The constructor syntax shown above is really a shorthand for using the constructor keyword:

class Foo constructor(var count: Int) {
  fun something() {
    count += 1
    println("something() was called $count times")
  }
}

fun main() {
  val foo = Foo(0)

  foo.something()
  foo.something()
  foo.something()

  println("the final count was ${foo.count}")
}

For most classes, with zero or one constructors, you will not see the constructor keyword used. It becomes more important when you have multiple constructors, including private constructors.

Init Blocks

Compared with Java and Ruby constructors, though, our Kotlin constructors are missing something: a body. All we are doing is declaring a list of parameters that can be supplied to the instance of the class.

Kotlin instead uses an init block.

Syntax-wise, an init block resembles a Java static block: a set of braces-wrapped statements preceded by a keyword. In Java, the static block is executed once for the class and is used to initialize complex static fields. In Kotlin, an init block is executed once for each instance and serves as a baseline constructor body:

class Foo(val sillyCount: String) {
  var count = 0

  init {
    count = sillyCount.toInt()
  }

  fun something() {
    count += 1
    println("something() was not called $count times")
  }
}


fun main() {
  val foo = Foo("7")

  foo.something()
  foo.something()
  foo.something()

  println("the final count was ${foo.count}")
}

Here, inexplicably, we are passing in a String representation of an initial value to use for the count, rather than passing in the var count as we did before. The init block is used to initialize count from sillyCount as part of setting up our instance of Foo. There is a simpler way to handle this, via property initialization, that we will explore more in the chapter on properties.

init blocks have a couple of other distinctions, particularly when compared to Java/Ruby constructors:

Parameters Sans var Or val

Sometimes, you will see constructor parameters that do not have the var or val keyword. They just have the parameter name and type. They are still constructor parameters, but they are not properties. You cannot refer to them from the functions of your class. You can refer to them from init blocks, though:

class Foo(sillyCount: String) {
  var count = 0

  init {
    count = sillyCount.toInt()
  }

  fun something() {
    count += 1
    println("something() was not called $count times")
  }
}

fun main() {
  val foo = Foo("7")

  foo.something()
  foo.something()
  foo.something()

  println("the final count was ${foo.count}")
}

This is the same as the preceding example, just without the var. It works, because the only place we refer to sillyCount is from an init block.

Having Multiple Constructors

Some Kotlin classes have no constructor, using only the default zero-parameter constructor. Some Kotlin classes have one constructor. And a handful of classes will have more than one constructor.

The primary constructor appears in the class declaration itself, as we have seen. Other constructors, if they exist, are called “secondary constructors”, and they somewhat resemble ordinary functions:

class Foo(var count: Int) {

  constructor(sillyCount: String) : this(sillyCount.toInt()) {
    // could have code here if needed
  }

  fun something() {
    count += 1
    println("something() was not called $count times")
  }
}


fun main() {
  val foo = Foo("7")

  foo.something()
  foo.something()
  foo.something()

  println("the final count was ${foo.count}")
}

A primary constructor has no function body — any such code goes into an init block. Secondary constructors, though, can have bodies, the way that functions do, but only if needed.

Secondary constructors must arrange to call the primary constructor. This is handled by having a this() call after the constructor parameter list, separated from that list via a colon. The this() call needs to match the parameter list of the primary constructor — in the example shown above, the secondary constructor needs to provide a Int to the primary constructor.

Default Parameter Values

Having multiple constructors is comparatively common in a language like Java, as through Java 8, there was no support for default parameter values. Hence, if you wanted to allow for both simple and complex object instantiation, you needed to declare all of the necessary constructors, perhaps chaining from one to another. For example, Android developers who have created custom View classes might be familiar with the four View constructors:

public View(Context context) {
  // a ton of code
}

public View(Context context, @Nullable AttributeSet attrs) {
  this(context, attrs, 0);
}

public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
  this(context, attrs, defStyleAttr, 0);
}

public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
  int defStyleRes) {
  this(context);

  // another ton of code
}

Here, each of the constructors simply adds on another possible parameter to be supplied, and the constructors chain to other constructors to eliminate duplication of initialization logic.

Kotlin, like Ruby, dispenses with this, by allowing for you to define default values for your constructor parameters… just as you can on ordinary functions. The Kotlin equivalent of the View constructor set might look like:

class View(
  context: Context,
  attrs: AttributeSet? = null,
  defStyleAttr: Int = 0,
  defStyleRes: Int = 0
) {
  // two tons of code
}

Here, the latter three parameters all have default values defined, giving us the ability to call the constructor with one parameter, all four parameters, or combinations in between.

The above code snippet contains newlines in between the parameters. That is merely a matter of code formatting. Typical Kotlin will split long parameter lists up this way, with one parameter per line.

Also, attrs is shown as having a type of AttributeSet?. As was mentioned previously (briefly), the ? suffix indicates that this is a “nullable type”, and we will explore that in greater detail in an upcoming chapter.


Prev Table of Contents Next

This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.