Why are getters and setters "evil"?
If I have classes for names, addresses and in general, persons, how am I supposed to getFirstName(), getLastName(), getState() etc from another class or package?
If my subclass access database tables to retrieve a person's detail, I'd use setters to populate the variables, then I'd use getters to get them. Right?
I am not saying we should expose an object's processing methods, but I cannot see how to get around getters and set
Are there any diagramming tools, like ERwin for data modeling, specifically for designing OO diagrams?
Just so I can follow the flow of logic and sequence.
Knute Snortum wrote:I've never heard that getters are evil, but if you want to create an immutable object, then you don't want to use setters. You want to pass the arguments to the constructor so that the fields can be final.
That said, you can still use setters if there is a good reason.
If I want to get a patient's medical record from database tables and I use several subclasses for them, I don't see how they could be immutable because I ill be using the returned dataset and setters to populate the local variables.
Do you have practical examples of immutables in real live, other than math stuff like PI, natural log etc ( which I can get from Math class)
Thanks for the response.
AhFai Chan wrote:Do you have practical examples of immutables in real live, other than math stuff like PI, natural log etc ( which I can get from Math class)
I suspect the most common one is String, because we all use it.
And because it's immutable, the Java language has been able to develop around it to some extent. For example: since v5 (I think) you can now use Strings in switch statements, where you couldn't before.
But getting back to your question, the reason why public (very important) getters and setters are evil is that they expose too much of your class - and yes, even a getter can expose things you really don't want a "user" to know about.
If you're the driver of a Car, you don't really need to know what the engine looks like, do you?
Providing it starts when you turn the key, you're happy. For me, the ideal car would be one that has holes for putting in petrol; oil; windscreen, brake and power-steering fluid; water for the radiator; and leads for charging the battery if I need to. I'm not a mechanic, so the rest is completely redundant; and I really wouldn't care too much if manufacturers locked it all away from me so I can't screw anything up by "fiddling about".
The fact is that, in many cases, public (in bold again) getters and setters are just bloatware; and if you design your classes based on how they should behave, usually not needed. Do you see getters and setters in interfaces? Sometimes (eg, java.util.List); but when you do, it's because it's part of the required behaviour.
If I'm not explaining myself very well, have a look at this article; because it explains it far better than I can.
Those values are all doubles which are primitives. The concept of mutability does not apply to primitives. You can either reassign them or you can't (if marked final). The thing about primitives is that you can have hundreds of variables all pointing to the same value of a primitive but, unlike a reference type, they are all independent from one another. You can reassign one of them without affecting any of the others.
AhFai Chan wrote:. . . Do you have practical examples of immutables in real live, other than math stuff like PI, natural log etc . . .
Fred Kleinschmidt wrote:...the setter then sets the value and calculates the new area - once -so the user can call getArea() over and over without triggering another calculation.
I like that example, Fred. It shows that "area" is a property of your Shape class, but it need not be stored in your Shape class. If, as you suggest, your setWidth and setHeight methods always calculate the area, then area most likely would be stored in an instance of Shape. But, if your application were unlikely to make many calls to getArea (or you just didn't mind the overhead), calls to setWidth and setHeight might merely store those values and calls to getArea would compute the area, once on every call. Does the Shape client care about which implementation you chose? Until it makes some kind of performance difference that matters, I would say the answer is "no." The beauty of this is that you can change your implementation if you want to, and no client code that calls Shape's methods has to change.
The trick, for me, in accepting all this was to give up on the idea that for each getter a class has, that class has a corresponding private field. It might, but it need not. Indeed, when developing a system, one might start with a field as a stub for something to be done later. For example, suppose you have a WeatherStation class, and want to be able to query it for temperature. A getTemperature method seems obvious. But, some weeks down the road, you may buy the remote temperature sensor you're going to use and, when you do, getTemperature will have to call some library code that the vendor of that sensor provides. Until then, however, getTemperature can just return a value stored in a field (maybe that value is updated now and then by some thread you create to simulate changes in the weather). Again, clients of WeatherStation do not have to be coded in a way that knows or cares that getTemperature is merely getting a private field, nor that getTemperature is issuing a query that returns a value obtained by some remote device.
Good example of encapsulation.