contructors setters or both

G

glunk

I went to a Java class (training!) a while ago. The instructor was actually
a real programmer. I am used to Microsoft training in which the person doing
the training does not actually ever DO the work. Anyway, the instructor told
us it was a good idea to either set the values of instance variables by
passing them into the constructor OR by setter methods, but not both. One
class I am working on which was created by someone else has the values
passed into the constructor (with no zero parameter constructor) AND setter
methods. We were going to do this kind of thing


public MyClass (String lastName, String firstName) {

setLastName(lastName);
setFirstName(firstName);

}

to ensure that any setter code which may do something to the value is used.

But then, if you can see my other post entitled "getting used to Java -
question about 'style'" this seems to be calling a nonfinal method (the
setters) from within a constructor.

So far, in our project, we do not use the setters. I cannot think of why you
would want to have only one constructor with the params for the instance
variables AND the setter methods if you cannot use the setter methods within
the contructor.

Can someone comment on whether or not it is generally wise to not have
setters if the instance vars have to be set in the constructor? In this
example, I cannot even think of a value changing.

Thanks

S
 
C

Chris Smith

glunk said:
I went to a Java class (training!) a while ago. The instructor was actually
a real programmer. I am used to Microsoft training in which the person doing
the training does not actually ever DO the work. Anyway, the instructor told
us it was a good idea to either set the values of instance variables by
passing them into the constructor OR by setter methods, but not both.

I'm not sure exactly what your instructor was referring to here. What
he/she *may* have been talking about is that there are occasions where
you ought to consider writing an immutable class, in which there is no
way to change the data stored in an object after it has been created.
Examples from the core API include java.lang.String and
java.lang.Integer.

Immutable classes have a number of advantages, including that they can
be safely shared between threads and between pieces of the program,
without worrying that one piece of code will change the data in the
object and interfere with other code that is also using the same object.

However, once you've decided to make an object mutable (i.e., it can be
changed), there's no reason not to also provide a constructor that lets
you set an initial value. There's also no requirement that if you write
such mutator methods, that you use them from inside the class (although
you certainly can; see below). Mutators are quite convenient for
external use as well. For example, it's easier to say:

return new Appointment("Dr. Johnson", apptTime);

versus:

Appointment appt = new Appointment();
appt.setDoctor("Dr. Johnson");
appt.setTime(apptTime);
return appt;
We were going to do this kind of thing


public MyClass (String lastName, String firstName)
{
setLastName(lastName);
setFirstName(firstName);
}

to ensure that any setter code which may do something to the value is used.

But then, if you can see my other post entitled "getting used to Java -
question about 'style'" this seems to be calling a nonfinal method (the
setters) from within a constructor.

Yes, it is, assuming that the class is not final and that the mutator
methods are not final. Are you designing this class for use of
inheritance? If so, then you would indeed need to work this out.

For the most part, mutators aren't used from inside the class where you
use them, which would solve this problem for you. The most important
unit of encapsulation in an OO language is the class, and it's okay to
break encapsulation inside of a class, because you assume that you're in
control of all that code.

Of course, use of mutators even for private fields (sometimes called
self-encapsulation) can be a nice implementation convenience to avoid
duplicating code. In this case, one possibility might be to provide
both private mutators (for self-encapsulation within the class) and
public mutators (which just call the private mutators by default), and
then call the private mutators directly from the constructor. That
means you end up with *two* mutators for each field, though, which can
get unwieldly rather fast.
Can someone comment on whether or not it is generally wise to not have
setters if the instance vars have to be set in the constructor? In this
example, I cannot even think of a value changing.

Sounds like, in this case, you'd be better off going for an immutable
class, and not providing any mutators at all. It really depends on your
overall design, though, so I can't make that call for you.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
G

glunk

Chris Smith said:
I'm not sure exactly what your instructor was referring to here. What
he/she *may* have been talking about is that there are occasions where
you ought to consider writing an immutable class, in which there is no
way to change the data stored in an object after it has been created.
Examples from the core API include java.lang.String and
java.lang.Integer.

Immutable classes have a number of advantages, including that they can
be safely shared between threads and between pieces of the program,
without worrying that one piece of code will change the data in the
object and interfere with other code that is also using the same object.

However, once you've decided to make an object mutable (i.e., it can be
changed), there's no reason not to also provide a constructor that lets
you set an initial value. There's also no requirement that if you write
such mutator methods, that you use them from inside the class (although
you certainly can; see below). Mutators are quite convenient for
external use as well. For example, it's easier to say:

return new Appointment("Dr. Johnson", apptTime);

versus:

Appointment appt = new Appointment();
appt.setDoctor("Dr. Johnson");
appt.setTime(apptTime);
return appt;


Yes, it is, assuming that the class is not final and that the mutator
methods are not final. Are you designing this class for use of
inheritance? If so, then you would indeed need to work this out.

For the most part, mutators aren't used from inside the class where you
use them, which would solve this problem for you. The most important
unit of encapsulation in an OO language is the class, and it's okay to
break encapsulation inside of a class, because you assume that you're in
control of all that code.

Of course, use of mutators even for private fields (sometimes called
self-encapsulation) can be a nice implementation convenience to avoid
duplicating code. In this case, one possibility might be to provide
both private mutators (for self-encapsulation within the class) and
public mutators (which just call the private mutators by default), and
then call the private mutators directly from the constructor. That
means you end up with *two* mutators for each field, though, which can
get unwieldly rather fast.


Sounds like, in this case, you'd be better off going for an immutable
class, and not providing any mutators at all. It really depends on your
overall design, though, so I can't make that call for you.


Thanks. You are very good at explaining.

S
 
G

Gorf

glunk said:
I went to a Java class (training!) a while ago. The instructor was actually
a real programmer. I am used to Microsoft training in which the person doing
the training does not actually ever DO the work. Anyway, the instructor told
us it was a good idea to either set the values of instance variables by
passing them into the constructor OR by setter methods, but not both. One
class I am working on which was created by someone else has the values
passed into the constructor (with no zero parameter constructor) AND setter
methods. We were going to do this kind of thing


public MyClass (String lastName, String firstName) {

setLastName(lastName);
setFirstName(firstName);

}

to ensure that any setter code which may do something to the value is used.

But then, if you can see my other post entitled "getting used to Java -
question about 'style'" this seems to be calling a nonfinal method (the
setters) from within a constructor.

So far, in our project, we do not use the setters. I cannot think of why you
would want to have only one constructor with the params for the instance
variables AND the setter methods if you cannot use the setter methods within
the contructor.

Can someone comment on whether or not it is generally wise to not have
setters if the instance vars have to be set in the constructor? In this
example, I cannot even think of a value changing.

Not really. I suspect they've missed out a default constructor. It is
generally good practice to *always* call setter methods due to the fact that
you have one point where you can stick a breakpoint and see EVERY access to
that variable. Otherwise some bug in your code could be a MyClass.firstName
= "Bob" and it would be very difficult to track down why your clients name
has changed to Bob.

There are other reasons such as encapsulation and readability, but this is o
ne which can show an instant benefit.

Just my 0.02p.
 
C

Chris Riesbeck

Chris Smith said:
Sounds like, in this case, you'd be better off going for an immutable
class, and not providing any mutators at all. It really depends on your
overall design, though, so I can't make that call for you.

For me, though, sooner or later, my classes end up needing to be
Java beans, in order to play well with other tools, so they end up
needing the default constructor and get/set methods.

Fortunately, you can always start immutable and add these
later as needed. Just avoid calling those public non-final
mutators in the constructor as already noted.
 
C

Chris Smith

Chris said:
For me, though, sooner or later, my classes end up needing to be
Java beans, in order to play well with other tools, so they end up
needing the default constructor and get/set methods.

Incidentally, you don't need mutators to be a JavaBean. You'd just end
up with properties that are read-only. Depending on how you use
JavaBeans, this could very easily be good enough.

In general, this really contradicts a lot of well-accepted design
practice in Java, which generally greatly favors the use of immutable
objects. In fact, I'd guess the default rule would be to make value
objects immutable unless you've got a really good reason to do
otherwise. Of course this doesn't apply to GUI components (aside from
their being mutable anyway, so immutability is not a choice; it also
just doesn't make sense for an object whose identity is clearly separate
from its state), but it would apply to a lot of core logic classes
within an application.

That's not to say you're wrong, but I'm curious what tools we're talking
about here, which would need to interact with all (or a large percentage
of) your classes as JavaBeans.
Fortunately, you can always start immutable and add these
later as needed.

That's fairly tricky. Converting an immutable class to a mutable one is
easy enough in text, but requires a full audit of surrounding code by
someone knowledgable in the application's concurrency strategies and
other logic. There are just too many things you can do with immutable
objects that you can't do with mutable ones.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
C

Chris Smith

Gorf said:
Not really. I suspect they've missed out a default constructor. It is
generally good practice to *always* call setter methods due to the fact that
you have one point where you can stick a breakpoint and see EVERY access to
that variable.

Your debugger won't do this for you? Eclipse calls it a "watchpoint".

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
C

Chris Riesbeck

Chris Smith said:
Incidentally, you don't need mutators to be a JavaBean. You'd just end
up with properties that are read-only. Depending on how you use
JavaBeans, this could very easily be good enough.

Tools that construct a bean do it by calling the
default constructor and then the mutators.
In general, this really contradicts a lot of well-accepted design
practice in Java, which generally greatly favors the use of immutable
objects.
...
That's not to say you're wrong, but I'm curious what tools we're talking
about here, which would need to interact with all (or a large percentage
of) your classes as JavaBeans.

java.beans.XMLEncode/Decode, and similar reflection-based
bean-XML or bean-DB mappers.

There's no standard convention to tell code that it can make
a bean with all its parts by calling some multi-arg constructor.
The only way is to call the default constructor then setXxxx()
for each property xxx.

I wish there was since I would use immutable classes a lot more.
 
C

Chris Smith

Chris said:
Tools that construct a bean do it by calling the
default constructor and then the mutators.

Indeed, tools that create beans definitely do need mutators to set their
state. If, on the other hand, you were creating objects on your own and
then using them as beans elsewhere, then declaring the properties to be
read-only would be quite acceptable.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
T

Tony Morris

Not really. I suspect they've missed out a default constructor. It is

Provided that setter (mutator) is not overrideable.

--
Tony Morris
(BInfTech, Cert 3 I.T.)
Software Engineer
(2003 VTR1000F)
Sun Certified Programmer for the Java 2 Platform (1.4)
Sun Certified Developer for the Java 2 Platform
 
G

Gary Labowitz

Chris Smith said:
Your debugger won't do this for you? Eclipse calls it a "watchpoint".

This is more than just a debugging issues. With setter/getter methods it
allows for logging of access/setting of fields within the application.
Further, if the internal storage of the fields is encrypted, hashed, or
derived (say, from a DB access or calculation) then you must use private
setter/getter methods called from the public interface. I recommend using
setter/getter methods when security and/or data validation is needed before
allowing field access.
 
C

Chris Smith

Gary said:
This is more than just a debugging issues. With setter/getter methods it
allows for logging of access/setting of fields within the application.

Since I've never had such a requirement, I can't say that I have ever
had such a requirement. Logging is, in my experience, required at a
much higher level than setting a simple field.
Further, if the internal storage of the fields is encrypted, hashed, or
derived (say, from a DB access or calculation) then you must use private
setter/getter methods called from the public interface. I recommend using
setter/getter methods when security and/or data validation is needed before
allowing field access.

There's the difference. Mutators and accessors are important for this
reason in a public interface; but within a class, private accessors
and/or mutators are a part of the implementation of the class. Should
the implementation change so that they become needed, then they can be
added as the occasion arises. Again, a decent IDE can automate this
process for you; Eclipse calls it "self-encapsulate field". But even
without that, it's easy enough to use a text search function to find
occurrences of a field name and replace them with a call to private
get/set methods.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top