Why do we use getter and setters if we can do the same work by
declaring the public data members.
Your answer will be appriciable.
Imagine that you have a large system involving these two
classes:
class First {
public double area; // must be non-negative
}
class Second {
private double area; // must be non-negative
public double getArea() {
return area;
}
public void setArea(double newArea) {
if (newArea < 0)
throw new IllegalArgumentException();
area = newArea;
}
}
Now suppose a problem arises: Somebody, somewhere in this large
and complex system calculates an erroneous area of -42.3 and stores
it in an instance of one of these classes. If it's a Second, the
exception will lead you straight to the culprit. If it's a First,
you may have a very long debugging job in front of you. Using a
setter allows you to apply sanity-checks and other processing;
using a public member leaves you completely at the mercy of the
outside code, and with no opportunity to take extra action when
a field value changes.
Here's another situation:
class Temperature {
private double celsius;
private double fahrenheit;
public void setCelsius(double newCelsius) {
celsius = newCelsius;
fahrenheit = (celsius + 40) * 9 / 5 - 40;
}
public void setFahrenheit(double newFahrenheit) {
fahrenheit = newFahrenheit;
celsius = (fahrenheit + 40) * 5 / 9 - 40;
}
public double getCelsius() {
return celsius;
}
public double getFahrenheit() {
return fahrenheit;
}
}
After this class has been in use for a while (and lots of people
you don't even know are using it), you decide it's a waste of space
to store the temperature in both scales. So you settle on storing
only the Celsius value, converting to and from Fahrenheit at need:
class Temperature {
private double celsius;
public void setCelsius(double newCelsius) {
celsius = newCelsius;
}
public double getCelsius() {
return celsius;
}
public void setFahrenheit(double newFahrenheit)
celsius = (newFahrenheit + 40) * 5 / 9 - 40;
}
public double getFahrenheit() {
return (celsius + 40) * 9 / 5 - 40;
}
}
What must the users of your class do differently? NOTHING! By
shielding the data behind methods, you have allowed yourself to
change the data representation. You could add setKelvin() and
getKelvin() methods quite easily, again without disturbing any
existing code that uses your class. I submit that it would have
been extremely difficult if not impossible to carry out these
modifications if you had exposed the underlying data fields.
"Getter" and "setter" are ordinarily used to refer to methods
that don't do much work: A "setter" usually stores its argument
value in a data field (perhaps with a few sanity checks and perhaps
changing a related field to maintain agreement), and a "getter"
typically just returns whatever is stored in some field. They may
remain this way -- but the fact that they are methods and that the
underlying data is hidden from outsiders gives you the freedom to
change things later, if the need arises. If you expose the data
fields, those fields' names, types, and significance all become part
of your class' API, something you can't change without risking
breakage in the code that uses your class.