Getters and Setters

S

Scott.R.Lemke

Before I start, I understand the implementation of getters and setters
and how to use them, I'm not asking about how, I'm asking about why.
From day 1 of ever seeing a Java class, getters and setters were said
to be needed to "preserve encapsulation" But, how is the following
encapsulating anything:

Class Foo{
private int bar;

public int getBar() { return bar; }
public void setBar(int newBar) { bar = newBar; }
}

The basic principle behind encapsulation is information hiding.
Throwing a layer between the implementation details of the class, with
the public interface, giving me the ability to change the
implementation without changing the interface.

I would argue that the above example, which I am sure everyone here has
written before, many times, not only does not provide encapsulation,
but breaks 2 basic principles without the developer doing it
intentiolly; Never allow your objects to get into an illegal state, I
could introduce an illegal value through the setter, and keep your
instance values private, someFoo.getBar() is essentially an alias for
someFoo.bar.

I may be looking at this the wrong way, it may even be my style coming
into play. To me, a proper getter/setter would be something like the
following:

Class Moo{
private Bubba aBubba;

public BubbaInterface getBubba() { return aBubba;}
public void setBubba(BubbaInterface newBubba) {
if(newBubba.isValidBubba()) aBubba = newBubba;}
}

Here, I am hiding the implementation, as I am dealing in interfaces,
and for all intents and purposes, the user of this class has no idea if
I have a Bubba or some other class that implements BubbaInterface as a
member variable.

I guess my question is manyfold. Is the use of getters and setters on
primitives, or even concrete classes, providing encapsulation. If the
getters and setters do nothing with the in/out values, are they nothing
more than macros? Does a getter that does nothing more than return a
member variable break security?

I'm sure there are more questions in my head somewhere, but this should
be a good start.
 
M

Matt Humphrey

Before I start, I understand the implementation of getters and setters
and how to use them, I'm not asking about how, I'm asking about why.

to be needed to "preserve encapsulation" But, how is the following
encapsulating anything:

Class Foo{
private int bar;

public int getBar() { return bar; }
public void setBar(int newBar) { bar = newBar; }
}
The basic principle behind encapsulation is information hiding.
Throwing a layer between the implementation details of the class, with
the public interface, giving me the ability to change the
implementation without changing the interface.

I would argue that the above example, which I am sure everyone here has
written before, many times, not only does not provide encapsulation,
but breaks 2 basic principles without the developer doing it
intentiolly; Never allow your objects to get into an illegal state, I
could introduce an illegal value through the setter, and keep your
instance values private, someFoo.getBar() is essentially an alias for
someFoo.bar.


There's nothing that says that every property must have a naive getter and a
setter. Sometimes it just doesn't make sense--something more complex may
needed or it may just be overkill. Even a getter or setter that does
nothing more than set / return a value provides the opportunity to later
return a copy of a value or to perform some other validation without
modifying client code, which is a great benefit that costs very little.
Access to the instance variable directly prevents this opportunity.
I may be looking at this the wrong way, it may even be my style coming
into play. To me, a proper getter/setter would be something like the
following:

Class Moo{
private Bubba aBubba;

public BubbaInterface getBubba() { return aBubba;}
public void setBubba(BubbaInterface newBubba) {
if(newBubba.isValidBubba()) aBubba = newBubba;}
}

Here, I am hiding the implementation, as I am dealing in interfaces,
and for all intents and purposes, the user of this class has no idea if
I have a Bubba or some other class that implements BubbaInterface as a
member variable.

It's not clear to me why this example is more "proper" than your first. Are
you suggesting that every setter should perform a validation check, or that
all getter / setters must have both a getter and a setter and that they must
be backed by an instance variable, or that all values should be represented
by interfaces? Although "make getters and setters" is good general advice,
it can't be applied without thought to every case.

Also, I think you're suggesting here that because pervasive getter/setters
for accessible properties are considered a good idea, further information
hiding by pervasive use of interfaces / abstract classes is also a good
idea. Classes already provide a layer of encapsulation and because every
ordinary class can be the superclass of future subclasses, I find no need to
design extra layers that have no explicit purpose. In general, I tend to
base my designs on a high proportion of interfaces and abstract classes
because I find these provide lots of opportunity for later expansion. My
clients sometimes call it overdesign, but are grateful when new capabilities
can be added easily. There are complex trade-offs there.
I guess my question is manyfold. Is the use of getters and setters on
primitives, or even concrete classes, providing encapsulation. If the
getters and setters do nothing with the in/out values, are they nothing
more than macros? Does a getter that does nothing more than return a
member variable break security?

Getters and setters simplify design in general (via consistency) and make
future changes easier. Getters cannot return variables--they return values
and so cannot be any less secure than direct access to the property. By
using getters you gain the opportunity to prevent access to modifying the
variable (you don't have to have a setter) and make it easier to change
security (or synchronization or anything else) access to the variable.
I'm sure there are more questions in my head somewhere, but this should
be a good start.

Cheers,
Matt Humphrey (e-mail address removed) http://www.iviz.com/
 
E

Eric Sosman

Before I start, I understand the implementation of getters and setters
and how to use them, I'm not asking about how, I'm asking about why.

to be needed to "preserve encapsulation" But, how is the following
encapsulating anything:

Class Foo{
private int bar;

public int getBar() { return bar; }
public void setBar(int newBar) { bar = newBar; }
}

The basic principle behind encapsulation is information hiding.
Throwing a layer between the implementation details of the class, with
the public interface, giving me the ability to change the
implementation without changing the interface.

I would argue that the above example, which I am sure everyone here has
written before, many times, not only does not provide encapsulation,
but breaks 2 basic principles without the developer doing it
intentiolly; Never allow your objects to get into an illegal state, I
could introduce an illegal value through the setter, and keep your
instance values private, someFoo.getBar() is essentially an alias for
someFoo.bar.

I may be looking at this the wrong way, it may even be my style coming
into play. To me, a proper getter/setter would be something like the
following:

Class Moo{
private Bubba aBubba;

public BubbaInterface getBubba() { return aBubba;}
public void setBubba(BubbaInterface newBubba) {
if(newBubba.isValidBubba()) aBubba = newBubba;}
}

Here, I am hiding the implementation, as I am dealing in interfaces,
and for all intents and purposes, the user of this class has no idea if
I have a Bubba or some other class that implements BubbaInterface as a
member variable.

I guess my question is manyfold. Is the use of getters and setters on
primitives, or even concrete classes, providing encapsulation. If the
getters and setters do nothing with the in/out values, are they nothing
more than macros? Does a getter that does nothing more than return a
member variable break security?

I'm sure there are more questions in my head somewhere, but this should
be a good start.

Getters and setters encapsulate primitive values to the
extent that they hide the fact that the values are stored in
primitive class members. The value returned by getBar() is
necessarily an int, but that doesn't mean it's stored as an
int primitive: You might decide to store it as a String of
Roman numerals, if that makes sense for the class as a whole.

In less artificial classes than the snippets you show,
the members usually have some significance and may be
interrelated. For example, you might have a class that holds
not only the int `bar' but also the smallest prime larger
than `bar'. From the "outside" it might appear that setBar()
and getBar() are just trivial store and fetch (they store what
you say to, and retrieve exactly what you stored), but setBar()
would also arrange to maintain `primeBiggerThanBar' as needed.
Then again, maybe it wouldn't: Perhaps getBiggerPrime() would
compute it on the fly when asked -- look! You've just hidden
an implementation detail from the outside world!

Even in a class that really, truly does nothing except
serve as a holder for an int, the getter/setter pattern can
turn out to be useful. Here's the original class:

public class IntHolder {
private int value;
void set(int newValue) { value = newValue; }
int get() { return value; }
}

One day, I find myself using a lot of IntHolder instances in
connection with a GUI, and I realize that it would be handy
to be able to update the GUI whenever a value changes. So
I add some functionality to IntHolder, getting it to fire
ChangeEvent notices to registered ChangeListeners:

public class IntHolder {
private int value;
void set(int newValue) {
if (newValue != value) {
value = newValue;
fireChangeEvents();
}
}
int get() { return value; }
void addChangeListener(ChangeListener nosy) {
...
}
void fireChangeEvents() {
...
}
}

The class is still just a holder for a value, but now it can
be an active participant in my overall program design.

A class member, even a primitive class member, is seldom
"just" a value. Even if the original class implementation
presents no special reason to use getters and setters, it
is often a good idea to implement them anyhow because reasons
to want them have a way of cropping up later. Maybe you'll
want to add instrumentation to study the distribution of values
for performance reasons, maybe you'll realize that the int is
a count of something and really ought to be non-negative (and
you'd like to find and exterminate the rascal who keeps setting
it to negative eighty-six!), maybe some other consideration
will arise. If you've used setters and getters you can manage
this sort of change conveniently -- but if you just decided to
expose `bar' as a public member, you're stuck.
 
C

Chris Smith

I guess my question is manyfold. Is the use of getters and setters on
primitives, or even concrete classes, providing encapsulation. If the
getters and setters do nothing with the in/out values, are they nothing
more than macros? Does a getter that does nothing more than return a
member variable break security?

Good questions, actually. Here are my thoughts, which you may or may
not agree with. I'm sure you'll get others.

The first thing to understand is that accessor and mutator methods (aka
"getters" and "setters") constitute a punt in OO design, although
generally speaking a necessary one. As such, you are right to suspect
them to some extent, and to retain some amount of distaste for their
use. Whenever it is possible to avoid them and write a correct and
well-structured application with a reasonable time frame and resources,
it's very likely a good idea to do so. There definitely is an
unfortunate tendency to overuse these constructs to avoid better OO
design.

That being said, it is fairly common that the purpose of a class really
*is* just to hold some data together and be able to treat it as one
thing. In the extreme case, the need for direct access to member
information comes from the system requirements. A banking application
would be useless if you couldn't get an account balance from it, for
example. A payroll application in which it is not possible to set an
employee's base salary makes itself unusable. In these cases, there are
actual requirements related to getting and setting values of objects,
and a corresponding need to provide that functionality in the interface
of a class.

When you examine these extreme cases closely, you end up with a common
thread: when we need direct access to the information that constitutes a
class as part of the application's imediate requirements, it's because
there's some greater abstraction that encompasses more than just the
software system. For example, why do we need to set an employee's base
salary for the payroll system? Inevitably there is some larger system
that can be said to determine the employee's base salary, but: (1) it
extends outside of this software system and the knowledge available to
the system, including within the formula the employee, her boss,
husband, children, family financial needs, the company's profits and
philosophies, etc.; and (2) it's not even algorithmic in nature, but
rather evolves through an extended process of trial and error.
Therefore, rather than creating the ultimate payroll system in which
there is never any need to set an employee's base salary, we must punt
and provide a mechanism to directly manipulate what might otherwise be
internal state of the employee.

The same is true, of course, on a smaller scale. If the "internal"
state of the employee can depend on factors outside the software system,
then it stands to reason that concerns that we'd like to be private to
module A are also in truth dependent on a number of factors from modules
B and C. Thus, it turns out that this imperfect encapsulation (having
acknowledged the need to break it due to the above paragraph) is in
tension with modular design, and can therefore make it difficult to
build scalable software if it is followed as an absolute unbendable
maxim. Hence, we often introduce accessors and mutators in order to
build modular boundaries where it would be otherwise challenging or
impossible to prevent code from breaking that boundary or creating too
complex an interface betweent the modules. This is why, for example,
the JavaBeans specification (which is basically just a formalism for
accessors and mutators) is often used for interactions between distinct
peices of software: classes and ORM products; business objects and web
presentation components such as JSPs; GUI components and visual design
tools; and so on. The use of accessors and mutators allows stronger
modular boundaries to be built by breaking abstractions that tend to
extend across that boundary.

The negative side of this, of course, is that abstractions aid program
design and comprehension at a higher level. Building modular boundaries
at the wrong places leads to breaking too many abstractions, and the
result is the OO equivalent of spaghetti code: only trivial abstractions
that don't belong or have much significance in the problem domain and
don't much help with program comprehension much if at all. The trick is
to build the modular boundaries of the program design in the right
places, to preserve as many good abstractions as possible while still
breaking up the program structure into digestible chunks.

Regarding the code you posted, and the related techniques, I'd caution
you that there is value in simplicity. If there is some reason to make
use of BubbaInterface, for example, then go ahead and use it. However,
if there's no benefit from it right now, then there may not be any
benefit in the future either. Here you'll need to distinguish between a
published interface, may be used by code over which you have no control,
and a non-published interface. In the former case, there may be some
justification for the extra complexity; but in the latter case, agile
programming teaches a concept called YAGNI (You Aren't Gonna Need It)
that applies here, and I agree with it. As a rule of thumb, always add
complexity at the last possible moment.

That's incomplete to be sure, but it's a start.
 
D

Dimitri Maziuk

(e-mail address removed) sez:
....
I guess my question is manyfold. Is the use of getters and setters on
primitives, or even concrete classes, providing encapsulation. If the
getters and setters do nothing with the in/out values, are they nothing
more than macros? Does a getter that does nothing more than return a
member variable break security?

I'm sure there are more questions in my head somewhere, but this should
be a good start.

I really wish Gosling et.al. looked at Delphi back when and borrowed
their "property" keyword (Microsoft apparently did with C#).

private int bubba;
private void setBubba( int newval );

public property int Bubba read bubba write setBubba;

-- allows you to switch implementation between direct access
and getter/setter method without changing the interface, is
much closer to OO idea of "properties and methods", is less
typing for the user. (Read or write clause can be omitted
for write/read-only properties.) Oh well...

To answer your question, you don't have to use getter/setters
that way. A getter may calculate its return on the fly, a seter
may sanitize its parameter(s) etc. In fact, if you don't do any
of those things, you're better off simply declaring your field
public.

Dima
 
D

ducnbyu

Before I start, I understand the implementation of getters and setters
and how to use them, I'm not asking about how, I'm asking about why.

Because it is general in nature. It works when details need to be
hidden and when there are no details.

I like IDEs (i.e. Eclipse). It saves me from having to go open up the
class documentation. If I have an object and I need to get some
information from it, I may not even know if that information is made
public. Type in "foo.get" and look through the short list of things
that can be got from foo. As I scroll through the list I see the
javadoc to the right. Nice.

Imagine my surprise when I go to (I'm speaking SWT here) "canvas.get"
hmm there's no getHeight() in here. Well the list is short so I scroll
around forward and backward and come about the getBounds() method,
javadoc confirms that's what I need so I hit Return to complete the
method name and type ".get" so I have "canvas.getBounds().get" and up
pops the getters for Bounds.

"Hey, there's no getHeight() in here either!" What's up with that. So
I scroll around through that short list for a time and there's nothing
appropriate that reveals itself. So I backspace that last "get" out of
there to get the long list for Bounds and low and behold there's a
public property "height" so all along I needed
canvas.getBounds().height. Waste of time. Glad this is the exception
not the rule. What if we had to go through that for all objects
because we don't know if details were hiddent or not?
 
P

Patrick May

Before I start, I understand the implementation of getters and
setters and how to use them, I'm not asking about how, I'm asking
about why.

As much as possible, you should refrain from creating them.
Let's first consider mutators (setters). Josh Bloch makes the point
very well in "Effective Java":

"Classes should be immutable unless there's a very good
reason to make them mutable. . . . If a class cannot be
made immutable, you should still limit its mutability
as much as possible."

http://www.javapractices.com/Topic29.cjp goes into greater detail of
the benefits of immutable classes.

Except for unusual cases such as the access layer to a database,
the internal state of an object should not be of interest to any other
object and should only be modified by its own methods. This leads to
the issue of accessors (getters).

Providing accessors encourages a programming style where some
objects get information from other objects, make decisions based on
that information, and take actions (often involving mutators). This
violates the "Tell, don't ask" principle (see
http://www.pragmaticprogrammer.com/ppllc/papers/1998_05.html and
numerous other Google hits for more detail).

The benefit of OO is that it allows developers to manage
complexity by focusing on behavior and message passing. In a good OO
design, the number of accessor and mutator methods will be very
restricted.

Regards,

Patrick
 
E

Eddy Young

I may be looking at this the wrong way, it may even be my style coming
into play. To me, a proper getter/setter would be something like the
following:

Class Moo{
private Bubba aBubba;

public BubbaInterface getBubba() { return aBubba;}
public void setBubba(BubbaInterface newBubba) {
if(newBubba.isValidBubba()) aBubba = newBubba;}
}

Why not? If your application requires this validation?
I guess my question is manyfold. Is the use of getters and setters on
primitives, or even concrete classes, providing encapsulation. If the
getters and setters do nothing with the in/out values, are they nothing
more than macros? Does a getter that does nothing more than return a
member variable break security?

Well, getters and setters are not evil if your application requires
them -- CRUD-type applications often do.

To improve encapsulation, you do things such as returning a copy of the
member variable instead of the original reference.
I'm sure there are more questions in my head somewhere, but this should
be a good start.

Again: There is nothing wrong with getters and setters. Use them as
suit your application.

Eddy
 

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,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top