1

I am new to Kotlin. I want to write a class which holds data. I want two constructors. What I want is something like this:

class InstituteSearchDetails(var centerId: String) {

    lateinit var centerId: String;
    lateinit var instituteName: String;
    lateinit var city: String;

    init {
        this.centerId = centerId
    }

    constructor(instituteName: String, city: String) {
        this.instituteName = instituteName;
        this.city = city;
    }
}

But on secondary constructor line it says primary constructor call is required. I know some delegation is required which calls primary constructor from there. I can't call primary constructor from here. I am sorry if I am doing some silly mistake. I am new to this thing.

1 Answer 1

4

From the doc:

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:

Example:

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

Your code:

constructor(instituteName: String, city: String) : this("centerId") {
    this.instituteName = instituteName
    this.city = city
}

But it doesn't look like you have the centerId value in the secondary constructor.

You can have two secondary constructors:

class InstituteSearchDetails {

    lateinit var centerId: String
    lateinit var instituteName: String
    lateinit var city: String
    
    constructor(centerId: String) {
        this.centerId = centerId
    }

    constructor(instituteName: String, city: String) {
        this.instituteName = instituteName
        this.city = city
    }
}

But be aware that, for instance, centerId won't have been initialized if you use the second constructor and you will get an exception (UninitializedPropertyAccessException) if you try to access the centerId in that case.

Edit:

This is not possible in a data class because a data class requires a primary constructor with at least one val or var. If you have the primary constructor, then your secondary constructor should delegate to the primary constructor as well. Perhaps you can have all properties in a single primary constructor of a data class but with nullable properties. Or see Sealed class.

sealed class InstituteSearchDetails {

    data class InstituteWithCenterId(val centerId: String) : InstituteSearchDetails()
    data class InstituteWithNameAndCity(val name: String, val city: String) : InstituteSearchDetails()
    
}

fun handleInstitute(instituteSearchDetails: InstituteSearchDetails) {
    
    when (instituteSearchDetails) {
        is InstituteSearchDetails.InstituteWithCenterId -> println(instituteSearchDetails.centerId)
        is InstituteSearchDetails.InstituteWithNameAndCity -> println(instituteSearchDetails.name)
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Yes i dont have centerId value in secondary constructor. That is the problem.
Can i do same with data class ?
I don't think so. data class requires a primary constructor with at least one val or var. If you have the primary constructor, your secondary constructor should delegate to the primary constructor as well. Perhaps you can have all properties in a single primary constructor but with nullable properties.
Or you can consider sealed class. Check this answer and the doc.
I have updated the answer with sealed class as well, where you can use data class and avoid nullable properties as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.