avatarGabriel Shanahan

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

5511

Abstract

s-keyword">class</span> <span class="hljs-title class_">FiveFivesJava</span> { List<String> fiveFives = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span><>();

<span class="hljs-comment">// Initializer block, see </span>
<span class="hljs-comment">// https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html</span>
{
    <span class="hljs-keyword">for</span> (<span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i &lt;= <span class="hljs-number">4</span>; i++) {
        fiveFives.add(<span class="hljs-string">"Fives"</span> + i);
    }
}

}</pre></div><p id="56dd">The only thing that’s new in Kotlin is the header of the primary constructor (arguments and optional modifiers/annotations). For more information on the execution order in Java, as well as an explanation of why you should make absolutely sure you only call private or final methods during construction, <a href="https://lustforge.com/2014/02/08/dont-call-non-final-methods-from-your-constructor-please/">see here.</a></p><p id="8c84">In Kotlin, you can (and should) go one step further.</p><p id="a1a8">Notice that the only purpose of the <code>integer</code> argument was to be immediately assigned to a property. If only we could somehow say "this class has <i>these</i> properties, and expects their values to be specified as constructor arguments".</p><p id="c2a9">As it turns out, in Kotlin, we can:</p> <figure id="9ea5"> <div> <div> <img class="ratio" src="http://placehold.it/16x9"> <iframe class="" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fpl.kotl.in%2Fd6iYkPPTx&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2Fd6iYkPPTx&amp;image=https%3A%2F%2Fplay.kotlinlang.org%2Fassets%2Fog-image.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=kotl" allowfullscreen="" frameborder="0" height="300" width="800"> </div> </div> </figure></iframe></div></div></figure><p id="4926">Awesome!</p><p id="cab5">Remember, primary constructor arguments behave like any other arguments, and all the features that apply to normal function arguments (such as default values, named parameters, etc.) apply to primary constructor arguments as well.</p> <figure id="3a3c"> <div> <div> <img class="ratio" src="http://placehold.it/16x9"> <iframe class="" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fpl.kotl.in%2FV6eICDZaf&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2FV6eICDZaf&amp;image=https%3A%2F%2Fplay.kotlinlang.org%2Fassets%2Fog-image.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=kotl" allowfullscreen="" frameborder="0" height="300" width="800"> </div> </div> </figure></iframe></div></div></figure><h1 id="35e3">Secondary constructors</h1><p id="1c71">Classes can also declare secondary constructors, which are prefixed with <code>constructor</code>. Every secondary constructor must call the primary constructor, either directly or through another secondary constructor. This is done immediately via the <code>this()</code> keyword (a matching constructor is selected based on the signature).</p> <figure id="43e0"> <div> <div> <img class="ratio" src="http://placehold.it/16x9"> <iframe class="" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fpl.kotl.in%2FtCZ-hFjWH&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2FtCZ-hFjWH&amp;image=https%3A%2F%2Fplay.kotlinlang.org%2Fassets%2Fog-image.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=kotl" allowfullscreen="" frameborder="0" height="300" width="800"> </div> </div> </figure></iframe></div></div></figure><h1 id="088c">Exercises</h1><p id="5797">The following class represents an immutable <code>Person</code> object. Since we haven’t discussed properties in Kotlin yet, we purposefully avoid the usage of getters and setters for now, and use <code>public</code> <code>final</code> fields. We wish to be able to easily construct <code>Person</code>s with any combination of the fields (i.e. only <code>title</code> + <code>lastName</code>, or <code>firstName</code> + <code>middleName</code> + <code>lastName</code>, etc.). We solve this by adding a builder class.</p><p id="2b3e">We also want to simplify the object construction for certain “common cases” e.g. we want to be able to write <code>new Person(“Harry”, “Potter”)</code> instead of having to write</p><div id="7e14"><pre><span class="hljs-keyword">new</span> <span class="hljs-title class_">Person</span>.Builder() .setFirstName(“Harry”) .setLastName(“Potter”) .buildPerson()</pre></div><p id="e35f">As “common cases”, we (randomly) pick “<code>title</code> + <code>firstName</code> + <code>middleName</code> + <code>lastName</code>” and “<code>firstName</code> + <code>lastName</code>”. We would also like to include the combination “<code>title</code> + <code>lastName</code>” (e.g. Mr. Bean), but in this case, we have no option but to use the builder.</p><p id="2672">The class implementation follows. Your task is to p

Options

rovide the same functionality in Kotlin, so you experience firsthand how much simpler things get.</p><div id="8ac6"><pre><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">PersonJava</span> { <span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> String title; <span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> String firstName; <span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> String middleName; <span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> String lastName;

<span class="hljs-keyword">public</span> <span class="hljs-title function_">Person</span><span class="hljs-params">(
        String title, 
        String firstName, 
        String middleName, 
        String lastName
)</span> {
    <span class="hljs-built_in">this</span>.title = title;
    <span class="hljs-built_in">this</span>.firstName = firstName;
    <span class="hljs-built_in">this</span>.middleName = middleName;
    <span class="hljs-built_in">this</span>.lastName = lastName;
}

<span class="hljs-keyword">public</span> <span class="hljs-title function_">Person</span><span class="hljs-params">(
        String firstName, 
        String lastName
)</span> {
    <span class="hljs-built_in">this</span>(<span class="hljs-string">""</span>, firstName, <span class="hljs-string">""</span>, lastName);
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Builder</span> {
    <span class="hljs-keyword">private</span> <span class="hljs-type">String</span> <span class="hljs-variable">title</span> <span class="hljs-operator">=</span> <span class="hljs-string">""</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-type">String</span> <span class="hljs-variable">firstName</span> <span class="hljs-operator">=</span> <span class="hljs-string">""</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-type">String</span> <span class="hljs-variable">middleName</span> <span class="hljs-operator">=</span> <span class="hljs-string">""</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-type">String</span> <span class="hljs-variable">lastName</span> <span class="hljs-operator">=</span> <span class="hljs-string">""</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setTitle</span><span class="hljs-params">(<span class="hljs-keyword">final</span> String newTitle)</span> {
        title = newTitle;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setFirstName</span><span class="hljs-params">(<span class="hljs-keyword">final</span> String newFirstName)</span> {
        firstName = newFirstName;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setMiddleName</span><span class="hljs-params">(<span class="hljs-keyword">final</span> String newMiddleName)</span> {
        middleName = newMiddleName;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setLastName</span><span class="hljs-params">(<span class="hljs-keyword">final</span> String newLastName)</span> {
        lastName = newLastName;
    }

    <span class="hljs-keyword">public</span> Person <span class="hljs-title function_">buildPerson</span><span class="hljs-params">()</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Person</span>(
                title, 
                firstName, 
                middleName, 
                lastName
        );
    }
}

}</pre></div> <figure id="3bdd"> <div> <div> <img class="ratio" src="http://placehold.it/16x9"> <iframe class="" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fpl.kotl.in%2F0VxbgOKZ8%3Ffrom%3D26%26to%3D41&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2F0VxbgOKZ8%3Ffrom%3D26%26to%3D41&amp;image=https%3A%2F%2Fplay.kotlinlang.org%2Fassets%2Fog-image.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=kotl" allowfullscreen="" frameborder="0" height="300" width="800"> </div> </div> </figure></iframe></div></div></figure><p id="d6aa">Go back to <a href="https://readmedium.com/basic-class-syntax-c304635922ad">Basic Class Syntax</a>, jump to the <a href="https://readmedium.com/table-of-contents-c52573cfa291">Table of Contents</a>, or continue to <a href="https://readmedium.com/properties-introduction-fd98bc9c1056">Properties — Introduction</a>.</p><figure id="8ecd"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*biBSB579iezsNvEQ_NMLBg.png"><figcaption><a href="https://www.etnetera.cz/prace-u-nas?utm_source=medium&amp;utm_medium=GabrielShanahan&amp;utm_campaign=KotlinPrimer&amp;utm_content=join-our-team&amp;utm_term=KotlinPrimer#pozice">Join me in Etnetera</a></figcaption></figure></article></body>

Constructors

Primary and secondary constructors, init blocks, defining properties as constructor arguments

— — — — — — — — — — — — — — —

THE CURRENT VERSION OF THIS ARTICLE IS PUBLISHED HERE.

— — — — — — — — — — — — — — —

Tags: #KOTLIN FEATURE #EXERCISE

This article is part of the Kotlin Primer, an opinionated guide to the Kotlin language, which is indented to help facilitate Kotlin adoption inside Java-centric organizations. It was originally written as an organizational learning resource for Etnetera a.s. and I would like to express my sincere gratitude for their support.

It is recommended to read the Introduction before moving on. Check out the Table of Contents for all articles.

One of the differences between Java and Kotlin is how each language handles constructors.

In Java, constructors are methods with a special name. There can be any number of them, or none at all. They are all equivalent in terms of their properties — one is no more special than the other.

// A simple java class with a simple constructor
class MyIntegerJava {
    Integer myInteger;
    
    public MyIntegerJava(Integer integer) {
        myInteger = integer;
    }
}

In Kotlin, there are actually two different types of constructors — primary and secondary. Secondary constructors are basically no different from regular Java constructors, and we’ll talk about them in a bit.

Primary Constructors

Primary constructors (a concept taken directly from Scala) are special, because the body of the primary constructor is merged with the class definition. In other words, the class definition can also be interpreted as the primary constructor body.

If you need to execute code other than assignments, use an initializer block, denoted by init:

Code in initializer blocks effectively becomes part of the primary constructor. Multiple init blocks can be used - in that case, they are executed in order:

This can be useful if you have multiple properties that need custom initialization, and don’t want to mix all the code together.

This whole concept might seem weird, but it helps to realize that Java already allows almost all of this.

import java.util.Arrays;
import java.util.Collections;

class FiveFivesJava {
    List<String> fiveFives = new ArrayList<>();
    
    // Initializer block, see 
    // https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
    {
        for (int i = 0; i <= 4; i++) {
            fiveFives.add("Fives" + i);
        }
    }
}

The only thing that’s new in Kotlin is the header of the primary constructor (arguments and optional modifiers/annotations). For more information on the execution order in Java, as well as an explanation of why you should make absolutely sure you only call private or final methods during construction, see here.

In Kotlin, you can (and should) go one step further.

Notice that the only purpose of the integer argument was to be immediately assigned to a property. If only we could somehow say "this class has these properties, and expects their values to be specified as constructor arguments".

As it turns out, in Kotlin, we can:

Awesome!

Remember, primary constructor arguments behave like any other arguments, and all the features that apply to normal function arguments (such as default values, named parameters, etc.) apply to primary constructor arguments as well.

Secondary constructors

Classes can also declare secondary constructors, which are prefixed with constructor. Every secondary constructor must call the primary constructor, either directly or through another secondary constructor. This is done immediately via the this() keyword (a matching constructor is selected based on the signature).

Exercises

The following class represents an immutable Person object. Since we haven’t discussed properties in Kotlin yet, we purposefully avoid the usage of getters and setters for now, and use public final fields. We wish to be able to easily construct Persons with any combination of the fields (i.e. only title + lastName, or firstName + middleName + lastName, etc.). We solve this by adding a builder class.

We also want to simplify the object construction for certain “common cases” e.g. we want to be able to write new Person(“Harry”, “Potter”) instead of having to write

new Person.Builder()
    .setFirstName(“Harry”)
    .setLastName(“Potter”)
   .buildPerson()

As “common cases”, we (randomly) pick “title + firstName + middleName + lastName” and “firstName + lastName”. We would also like to include the combination “title + lastName” (e.g. Mr. Bean), but in this case, we have no option but to use the builder.

The class implementation follows. Your task is to provide the same functionality in Kotlin, so you experience firsthand how much simpler things get.

public class PersonJava {
    public final String title;
    public final String firstName;
    public final String middleName;
    public final String lastName;

    public Person(
            String title, 
            String firstName, 
            String middleName, 
            String lastName
    ) {
        this.title = title;
        this.firstName = firstName;
        this.middleName = middleName;
        this.lastName = lastName;
    }

    public Person(
            String firstName, 
            String lastName
    ) {
        this("", firstName, "", lastName);
    }

    public static class Builder {
        private String title = "";
        private String firstName = "";
        private String middleName = "";
        private String lastName = "";

        public void setTitle(final String newTitle) {
            title = newTitle;
        }

        public void setFirstName(final String newFirstName) {
            firstName = newFirstName;
        }

        public void setMiddleName(final String newMiddleName) {
            middleName = newMiddleName;
        }

        public void setLastName(final String newLastName) {
            lastName = newLastName;
        }

        public Person buildPerson() {
            return new Person(
                    title, 
                    firstName, 
                    middleName, 
                    lastName
            );
        }
    }
}

Go back to Basic Class Syntax, jump to the Table of Contents, or continue to Properties — Introduction.

Join me in Etnetera
Kotlin
Java
Programming
Constructor
Learning
Recommended from ReadMedium