Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Why do we have constructors if we can reassign things?  RSS feed

 
Justin Robbins
Ranch Hand
Posts: 121
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello all!

Having some fundamental confusion about understanding constructions and what their job is. I've often hear them described as "they are what initialize the objects instance variables to specific values", so for example if we had a person and set things up like:





I understand that now we have this reference variable p to an object that has two fields one of a String representing the person's name, and one field of an int representing the person's age. So we have customized the object and its COPY of the instance variables of the class declaration.


Why do we have a constructor if we could similarly just write it as:
Person p = new Person();
p.name = "Jim";
p.age = 50;

Wouldn't this essentially do the same thing? is it just because of convenience of constructors or is there another level to this?

Also, about constructors. I am confused about how they work.
We set up a method that shares the same name as the class, and that says to the compiler, this is the constructor, and therefore the parameter signature inside this method that match up with the "new" objects parameters gets assigned all the stuff the put in.
So essentially we call the method when we write Person(); then pass in some stuff and the constructor with that signature kicks in and says, the String n you passed in was "Jim" and the int a you passed in was 50

Then

this.name = n; // take the instance variable name of the class and assign it to String argument just passed in
this.age = a; // take the instance variable age of the class and assign it to the int argument just passed in

Is that correct?


Grateful for all help on these confusions
Thank you
 
Campbell Ritchie
Marshal
Posts: 56598
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Because your class shou‍ld have invariants, i.e. facts which are always true. You do not want to have a Person with no name or age. An invariant for a Person class will be that the age must always be ≥ 0. The constructor ensures that the fields are all given sensible values as soon as the object exists (which is called establishing the class invariants). If you establish the class invariants via the constructor, you can be sure they are all established before you can use the object. Otherwise you will find an object not in a consistent state before you start using it.
You do not want to write things like
p.age = -50;
You shou‍ld have all the fields private, so if there are going to be any changes those changes have go to go through methods. The methods can be designed so as to ensure that only “correct” values are accepted, so you can prevent anybody setting age to a negative value. Not like what I wrote above. The constructor can similar reject “incorrect” values.
 
Campbell Ritchie
Marshal
Posts: 56598
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Let's convert part of your post to code:-
Justin Robbins wrote:. . .. . .
What could happen (especially if you are using a multi‑threaded app) is that somebody manages to execute a line 1½ or a line 2½ when your object is not in a consistent state. In the case of line 2½, you actually have incorrect information about the age, and this error might not be noticed until much later. You are more likely to notice if you get a Person object without a name.
 
Carey Brown
Saloon Keeper
Posts: 3329
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

First off, using private fields would prevent the usage as you have it on lines 2 and 3. With private fields you'd need to supply setters if you want your class to be mutable.  If on the other hand, you design an immutable class (recommended where practical), then you'd have no setters at all, only getters and you'd the have to set the values in a constructor.
 
Justin Robbins
Ranch Hand
Posts: 121
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:Because your class shou‍ld have invariants, i.e. facts which are always true. You do not want to have a Person with no name or age. An invariant for a Person class will be that the age must always be ≥ 0. The constructor ensures that the fields are all given sensible values as soon as the object exists (which is called establishing the class invariants). If you establish the class invariants via the constructor, you can be sure they are all established before you can use the object. Otherwise you will find an object not in a consistent state before you start using it.
You do not want to write things like
p.age = -50;
You shou‍ld have all the fields private, so if there are going to be any changes those changes have go to go through methods. The methods can be designed so as to ensure that only “correct” values are accepted, so you can prevent anybody setting age to a negative value. Not like what I wrote above. The constructor can similar reject “incorrect” values.


Thank you

Still confused here. An invariant are things we want always true in our code, so constructors provide this? What if someone just created a person like:
Person p = new Person();
Wouldn't that just give all the defaults of the object?

How do we ensure that we establish all the invariants? rather confused about all this. Couldn't someone just create an object with parameters "gksgnsdkv" and "-50" all they want? what prevents them from doing that?

Just not getting this....
 
Carey Brown
Saloon Keeper
Posts: 3329
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you provide a constructor that takes name and age and DO NOT supply a default constructor, then your new Person() will generate a compile error, as it should.
 
Knute Snortum
Sheriff
Posts: 4288
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
How do we ensure that we establish all the invariants? rather confused about all this. Couldn't someone just create an object with parameters "gksgnsdkv" and "-50" all they want? what prevents them from doing that? 

Consider this code:

The parameters "name" and "age" can only be set through the constructor.  There they are tested for reasonableness.  Once set, the instance variables cannot change.  We can't really stop a Person from getting a name like "kjhfkajsdfh" but at least Person will have reasonable and legal values.
 
Justin Robbins
Ranch Hand
Posts: 121
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Carey Brown wrote:If you provide a constructor that takes name and age and DO NOT supply a default constructor, then your new Person() will generate a compile error, as it should.


Oh ok, so it's a way of forcing there to be one way and only one way of creating an object with a specific signature/set of attributes.

So once we've completed the class we allow users of this class the ability to access our objects but only in the way that it's been specified in the constructors signature, like if someone wanted to use our Person class. He would instantiate the person and would be forced to have to use the signature of the constructor (String, int) or else it wouldn't work, so it's a way of constraining the user to specific of doing things so that it makes logical sense with what the user can and cannot do to the code.

 
Carey Brown
Saloon Keeper
Posts: 3329
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Knute Snortum wrote:

I think you meant to check for null first.
 
Justin Robbins
Ranch Hand
Posts: 121
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Knute Snortum wrote:
How do we ensure that we establish all the invariants? rather confused about all this. Couldn't someone just create an object with parameters "gksgnsdkv" and "-50" all they want? what prevents them from doing that? 

Consider this code:

The parameters "name" and "age" can only be set through the constructor.  There they are tested for reasonableness.  Once set, the instance variables cannot change.  We can't really stop a Person from getting a name like "kjhfkajsdfh" but at least Person will have reasonable and legal values.


Thank you!
beginning to see how powerful the constructor is in "limiting" the user to specific results. Couldn't we just create an object and start assigning whatever we want there like:
Person p = new Person();
p.name = "Sam";
p.age = 15;

How's that different from initializing them in the constructor?

Also what if we do use the constructor like so:
Person p = new Person("Sasha" 30);
p.name = "Bill";
p.age = 34;

Cannot we just reassigning over and over again, doesn't this mess things up?
 
Carey Brown
Saloon Keeper
Posts: 3329
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Consider this:
You might think that the list will contain two Person references, one to "Sasha" and one to "Bill" but in fact both references in the list point to the same Person object. What you end up with is both Persons in the list referring to "Bill". The Person object with a name of "Sasha" is now named "Bill". This is where immutable classes provide some CYA.
 
Dave Tolls
Ranch Foreman
Posts: 3068
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Justin Robbins wrote:
How's that different from initializing them in the constructor?

Cannot we just reassigning over and over again, doesn't this mess things up?


If you look at Knute's code, though, there is no way to actually change the name or age that way.
Consequently his Person objects are protected against strange changes.

Also, if you look at Campbell's post earlier, having a constructor that produces a valid object (where validity is determined by your requirements) helps prevent people passing around invalid objects.
And I would class a Person with no name and (maybe) 0 age as invalid in most applications...hospital birth registers aside.
 
Knute Snortum
Sheriff
Posts: 4288
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Carey Brown wrote:
Knute Snortum wrote:

I think you meant to check for null first.

Ha!  Yeah, that makes more sense.
 
Campbell Ritchie
Marshal
Posts: 56598
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave Tolls wrote:. . . I would class a Person with no name and (maybe) 0 age as invalid in most applications...hospital birth registers aside.
But in a birth register or other location where there are small babies, you would not use the default values, but, as it says in the Java™ Tutorials, you would explicitly pass 0 for age.
 
Dave Tolls
Ranch Foreman
Posts: 3068
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I was being a little facetious as a birth register in a hospital holds rather more detail than name and age.
 
Campbell Ritchie
Marshal
Posts: 56598
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I thought it was more “Many a true w‍ord spoken in jest.”
 
Dave Tolls
Ranch Foreman
Posts: 3068
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Of course there's that one in the news recently as well...born twice.
Doubt there's many systems written to deal with that edge case.
;)
</detour>
 
Campbell Ritchie
Marshal
Posts: 56598
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave Tolls wrote:Of course there's that one in the news recently as well...born twice. . . .
I know about Nicodemus and John ch 3, but I hadn't see that story.
 
Dave Tolls
Ranch Foreman
Posts: 3068
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
http://www.bbc.co.uk/news/world-us-canada-37757031

And I promise I'll shut up now!
(Though if I were her I would be demanding double pressies)
 
Campbell Ritchie
Marshal
Posts: 56598
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you I found the story elsewhere and am thinking, “So what? I knew about fetal surgery twenty years ago.”
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!