Why do all secondary constructors have to call the primary constructor?


#1

I am writing some classes that need to be instantiated from more than one object type on different occasions. These classes will all end up with the same fields no matter the object used to create it. For example I want to create a class instance from a Map that contains the values I need to set. I also want to create a class instance from another arbitrary object that also contains the same fields but naturally they must be acquired in a different way to the Map and the class is not the same type so cannot be passed into the same constructor.

I have a solution to this using a companion object and writing static methods to create instances of the class from each object. But I don’t like it very much.

What I would like to be able to do is have multiple constructors that take different objects as arguments and do not have to call the primary constructor, as these secondary constructors take totally different arguments and they cannot be shared with the primary constructor. I also do not want to have an empty primary constructor and set default values for all my class attributes.

If any given constructor can guarantee all the fields in the object are initialized, why must there be a primary constructor? In other words, why can we not have multiple primary constructors?


#2

I don’t fully understand the problem…
Can you show some of the static methods, so I can understand?


#3

The fact that all other constructors have to call the primary constructor, makes the primary constructor the base case constructor.

The problem is, it is more natural to think of the primary constructor as the ‘main use case’ constructor, which may not be the same as the base case.

I wonder if anyone has a solution … such as allowing nominating a base case constructor.


#4

If any constructor can guarantee that all the fields are initialized, then the constructors have these fields in common and you can create a (private?) primary constructor.

I do think of the primary-constructor as the most important constructor.
The other constructors are in most cases just handy for destructuring an object by yourself.
When the other constructors have bodies, I know it’s doing more then just destructuring the object.
I like this way of this implementation a lot.

You however don’t need a primary constructor:

class Test{
    val value: Any
    
   constructor(map: Map<String, Int>) {
       value = map
   }
   constructor(array: Array<String>) {
       value = array
    }
}

But I personally don’t like this option, as it makes you look at every body to figure out if it does something other than destructuring the param


#5

The thing is, you don’t need to use a primary constructor. If you use “secondary” constructors only you can have as many as you want (like Java). There is even easy refactoring in intellij Kotlin plugin for this (just stand on the constructor, alt-enter, and choose move to body). At that point there is no primary constructor and other constructors don’t need to call it (of course they still need to call a super constructor (maybe implicitly).


#6

My static methods are essentially doing the same thing as your two secondary constructors in your other comment. That’s what I am looking for. Although it may not be perfect, better than what I have. Didn’t know you could do that. Thanks!


#7

you’re welcome.
Up to the next question :wink: