Constructors in Kotlin

26,596

Solution 1

Well init is not body of constructor. It is called after primary constructor with the context of primary constructor.

As given in Official documentation:

The primary constructor cannot contain any code. Initialization code can be placed in initializer blocks, which are prefixed with the init keyword:

class Customer(name: String) {
    init {
        logger.info("Customer initialized with value ${name}")
    }
}

Note that parameters of the primary constructor can be used in the initializer blocks. They can also be used in property initializers declared in the class body:

class Customer(name: String) {
    val customerKey = name.toUpperCase()
}

In fact, for declaring properties and initializing them from the primary constructor, Kotlin has a concise syntax:

class Person(val firstName: String, val lastName: String, var age: Int) {
    // ...
}

As per your question you can add a constructor to accept one parameter like following:

class Person(name: String, surname: String) {

    constructor(name: String) : this(name, "") {
        // constructor body
    }

    init {
        Log.d("App", "Hello");
    }
}

But it doesn't look right as we are unnecessary passing second argument empty string. So we can order constructor like following:

class Person(name: String) {

    constructor(name: String, surname: String) : this(name) {
        // constructor body
    }

    init {
        Log.d("App", "Hello");
    }
}

Hope it helps.

Solution 2

First way with empty values

// (name: String, surname: String)  default constructor signature
class Person(name: String, surname: String) {

    // init block , represents the body of default constructor 
    init {
        Log.d("primary", "Hello");
    }

    // secondary constructor 
    // this(name,"") call to default constructor
    constructor(name : String):this(name,""){
        Log.d("secondary", "Hello");
    }
}

why this(name,"")

If the class has a primary constructor, each secondary constructor needs to delegate to the primary constructor, either directly or indirectly through another secondary constructor(s). Delegation to another constructor of the same class is done using the this keyword:

or

kotlin won't allow to use null like this(name,null) so use ? to represent null values with type, surname: String?

class Person(name: String, surname: String?) {

    init {
        Log.d("primary", "Hello");
    }

    constructor(name : String):this(name,null){
        Log.d("secondary", "Hello");
    }
}

Solution 3

Inside the class use constructor keyword to create secondary constructor. Like :

class Person(name: String, surname: String) {
    init {
        Log.d("App", "Hello");
    }
    constructor(id: Int) {

    }
}

For more info check Secondary Constructors

EDIT:
Rule : If the class has a primary constructor, each secondary constructor needs to delegate to the primary constructor, either directly or indirectly through another secondary constructor(s). Delegation to another constructor of the same class is done using the this keyword.

class Person(val name: String) {
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}

So when you call secondary constructor, it calls primary constructor to initialize name and after that you do your stuff in secondary constructor. In example above the name is initialized by calling primary constructor.

Solution 4

Secondary Constructors

The class can also declare secondary constructors, which are prefixed with constructor:

class Person {
    constructor(parent: Person) {
        parent.children.add(this)
    } } 

If the class has a primary constructor, each secondary constructor needs to delegate to the primary constructor, either directly or indirectly through another secondary constructor(s). Delegation to another constructor of the same class is done using the this keyword:

class Person(val name: String) {
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    } }

see https://kotlinlang.org/docs/reference/classes.html Secondary Constructors part

Solution 5

This is how you create another constructor.

class Person(name: String, surname: String) {
    init {
        Log.d("App", "Hello");
    }
 constructor(id: Int) : this("example name", "example surname") {

}
}

Always remember that, the secondary constructor will have to reference the primary constructor and it's parameters using the this keyword.

Share:
26,596
N Sharma
Author by

N Sharma

I have done masters in Advanced Software Engineering. I have worked on various technologies like Java, Android, Design patterns. My research area during my masters is revolving around the Recommendation algorithms that E-commerce websites are using in order to recommend the products to their customers on the basis of their preferences.

Updated on July 09, 2022

Comments

  • N Sharma
    N Sharma almost 2 years

    I am learning Kotlin from official docs, I created one class like below where I created one constructor which has two parameters. Body of constructor is in init block.

    class Person(name: String, surname: String) {
        init {
            Log.d("App", "Hello");
        }
    }
    

    Well, I want to create one more constructor which will take one parameter in a constructor. What is the way to do in Kotlin

  • N Sharma
    N Sharma almost 7 years
    I have this code class Person(name: String, surname: String) { init { Log.d("Hello", "Hello $name $surname"); } constructor(name: String) { } } after adding secondary constructor, Android Studio hinting me Error:(10, 5) Primary constructor call expected
  • Alf Moh
    Alf Moh almost 7 years
    This is because, you will have to call the primary constructor using the this keyword. Writing an answer soon to demonstrate.
  • N Sharma
    N Sharma almost 7 years
    Does this(name) calls primary constructor ? If so can we log to check ?
  • Sachin Chandil
    Sachin Chandil almost 7 years
    this() is used to call constructor, its parameter signature defines which constructor to call.
  • N Sharma
    N Sharma almost 7 years
    Yep correct. Can we check is it calling primary constructor or not by logging ?
  • Sachin Chandil
    Sachin Chandil almost 7 years
    As given in documentation primary constructor does not have body, but you can put that code in init block, it should do the trick.
  • Farruh Habibullaev
    Farruh Habibullaev over 5 years
    One argument on this(name), if we consider the constructor as a special method or func, is not this(name) a return type?
  • Sachin Chandil
    Sachin Chandil over 5 years
    Return type for what? Constructors does not return any value.@FarruhHabibullaev