Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call a default constructor from another one in Kotlin

Tags:

kotlin

anko

In Kotlin, when a class has multiple constructors how can we call the designated (coming from iOS world I could not find a better name) constructor from within another constructor.

Let me show you an example

final class LoadingButton: LinearLayout {
    var text:String? = null

    constructor(context: Context, text: String) : this(context) {
        this.text = text
    }
    constructor(context: Context) : super(context) {
        val t = this.text
        this.view {
            button(t) { /* ... */}
        }
    }
}

Here if I do loadingButton("TEST", {}) that string is not propagated to the button because this(context) is called before the code inside the convenience constructor (sorry again :).

Can that be solved in Kotlin ? Something like

constructor(context: Context, text: String) {
    this.text = text
    this(context) 
}

EDIT

Just to clarify the idea since it's been asked, the idea is to write something like this in an activity :

onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    verticalLayout {
        loadingButton("Some text")
        //or
        loadingButton() { this.text = "Some text"}
}

This is obviously not that much useful but you get the idea. The text property can be known at construction or later on.

This is especially not useful since Kotlin has default values for parameters but I am studying the language and ran into this problem.

EDIT 2

Another clarification is that I'm using Anko for the layout, so the loadingButton methods look like this:

inline fun ViewManager.loadingButton() = loadingButton {  }
inline fun ViewManager.loadingButton(init: LoadingButton.() -> Unit) = ankoView({ LoadingButton(it) }, init)
inline fun ViewManager.loadingButton(text: String, init: LoadingButton.() -> Unit) = ankoView({ LoadingButton(it, text) }, init)
like image 446
apouche Avatar asked Mar 14 '16 17:03

apouche


People also ask

How do I call a constructor from another class in Kotlin?

In Kotlin, one secondary constructor can call another secondary constructor of same class. This is done by using this() keyword. For example: class myClass{

How do I call a constructor in Kotlin?

In Kotlin, you can also call a constructor from another constructor of the same class (like in Java) using this() .

How do you use a secondary constructor in Kotlin?

To do so you need to declare a secondary constructor using the constructor keyword. If you want to use some property inside the secondary constructor, then declare the property inside the class and use it in the secondary constructor. By doing so, the declared variable will not be accessed inside the init() block.

How do you call a constructor from another?

Example 1: Java program to call one constructor from another Here, you have created two constructors inside the Main class. Inside the first constructor, we have used this keyword to call the second constructor. this(5, 2); Here, the second constructor is called from the first constructor by passing arguments 5 and 2.

What is a constructor in Kotlin?

A constructor is a special member function that is invoked when an object of the class is created primarily to initialize variables or properties. A class needs to have a constructor and if we do not declare a constructor, then the compiler generates a default constructor. Kotlin has two types of constructors –

Is there a secondary constructor in Kotlin with JPA?

Kotlin secondary constructor 159 Kotlin with JPA: default constructor hell 3 Accessing Resources IDs using Kotlin & Anko 254 How to create empty constructor for data class in Kotlin Android 9 Moshi's Custom Adapter with RxAndroid & Retrofit & Kotlin

What is it () function in Kotlin?

It is a special member function that is called when an object is instantiated (created). However, how they work in Kotlin is slightly different. In Kotlin, there are two constructors:

What is a special member function in Kotlin?

It is a special member function that is called when an object is instantiated (created). However, how they work in Kotlin is slightly different. In Kotlin, there are two constructors: The primary constructor is part of the class header.


1 Answers

The code with a post-call to a constructor cannot exist on JVM since you MUST call super(...) before you do anything with the class itself. Think of it as if the super class contained a private field, you would have to initialise it before you can use it.

This is usually not a problem since you can call the constructors the other way around:

constructor(context: Context, text: String?) : super(context) {
    this.text = text
    this.view {
        button(text) { /* ... */}
    }
}
constructor(context: Context) : this(context, null)
constructor(context: Context, text: String) : this(context, text)

The code above does roughly the same as a default argument:

constructor(context: Context, text: String? = null) : super(context) {
    this.text = text
    this.view {
        button(text) { /* ... */}
    }
}

To make this code idiomatic (and concise), use a primary constructor:

class LoadingButton(context: Context, val text: String? = null): LinearLayout(context) {
    init {
        this.view {
            button(text) { /* ... */}
        }
    }
}

The terminology goes as following: designated - primary, convenience - secondary

See Classes and Inheritance - Kotlin Programming Language for more details.

like image 79
voddan Avatar answered Sep 28 '22 08:09

voddan