We've already seen overloaded constructors in the IDE, but let's see a few more examples.
Classes can have as many constructors as necessary.
The only restriction is that they must each have a unique signature.
The compiler has to be able to determine which to call
based on the initialization information provided when creating the objects.
If there's any ambiguity, the compiler won't guess, it will generate a compiler error.
Remember, once you declare any constructor,
then the compiler generated default constructor will no longer be provided.
Here's the player class again, and we've decided that we need three constructors.
The first is a no args constructor,
the second only expects a single string object
and the third expects a string and two integers.
Obviously, the signatures for these constructors are different so the compiler can tell them apart.
We could have more constructors depending on our class design.
Now let's implement these constructors.
In the first example,
we're implementing the no args constructor to initialize the object to name none,
health 0 and xp 0.
The values we initialize to are totally dependent
on what we want our objects in the game to look like when no initialization information is provided.
It's important that we initialize our objects to some state that we know.
We don't want garbage data in any of the attributes after they're created.
In the second constructor, we only have the name parameter provided.
So we set the name attribute to name val and then the health and xp to 0.
If we don't initialize health in xp, they'll contain garbage
and that leaves the object in an unknown state.
Finally, the third constructor
is given initialization values for all three attributes.
So we initialize name to name val, health to health val
and xp to xp val.
Now we have three ways to create player objects.
In this case, the empty object will be initialized by the no args
constructor and it will contain none 0 and 0.
Hero and villain will be initialized with the constructor that expects
a single string object, and they will be initialized to
hero 0 0 and villain 0 0, respectively.
The frank object will be initialized by the three args constructor,
and it will contain frank 100 and 4.
And finally, the enemy object will be created dynamically on the heap
and initialized by the three args constructor to enemy 1000 and 0.
As you can see overloading constructors is a super powerful way to provide many useful
initialization options for your classes,
also best practice is to initialize all class attributes
so that created objects do not contain any garbage data.