I am studying programming and although I feel like I have good knowledge in programming (been writing PHP, Javascript etc for years), I've never dived into the world of OOP. Because of this I am asking for a general answer for the situation I am in. I know that there always will be some exceptions, but I am looking for the most correct approach in this case.
Ok, so I have two classes, Game
and GameGraphics
. GameGraphics
will create an object of Game
and use all the methods it has. We recently learned that all variables a class should be private, so all the variables in Game
are accessed by GameGraphics
through getters and setters.
But, when I want to access the variables of Game
inside the Game
class, should I use the public methods, or just access the variables directly? What is the most correct approach to this?
I'm developing in Java, if that matters. And please excuse my lack of OOP-experience.
The two major reasons behind using accessor methods (getters and setters) to access variables of other classes are
- An ability to present accessors as members of an interface, and
- An ability to override an accessor in a subclass.
A slight drop in readability is a reasonable price to pay for these advantages, because they let you encapsulate the logic of your class, resulting in tighter control on your part.
Neither of these advantages applies when it comes to private methods: they cannot implement interface methods, and they cannot be overridden. In fact, Java compiler would often optimize them out altogether, especially the simpler ones.
That is why I would recommend going straight for the instance variables, rather than adding an extra layer that does not help readability, yet gets optimized out by the compiler.
I would recommend you to always use the accessor methods. Your program will be easier to debug later on.
Let me give a rather-common scenario. Let's say you notice how an attribute gets unexpectedly updated and you want to know the places in your codes where an attribute might get updated:
If you consistently use the setter to update the value. You can just search that field's setter method once throughout the project and you're done. There can possibly no other places in your codes where the value gets updated. Not even inside the class itself (remember: no direct field access except the accessor).
If you update the value both by using both the setter method and the direct field access,
You will have to search your project twice. First, by the setter method. And second, by the field. And note that all the results listed from that 2nd one are likely mixed-up (that attribute could be there in the search result because it is either being accessed or being updated).
Also, if you want to do some debugging and check some values whenever an attribute is being updated or accessed, you can just put the breakpoint either in its setter or getter method. Easy. You don't need to put the breakpoints in some other places.
This is more a matter of personal preference than anything else.
The reason you use getters\setters is mainly to hide the implementation from the invoking class (in your case GameGraphics). Which is nice when other developers need to use your code.
And your getters\setters access the members directly so calling them while they call your instance variables is a bit redundant.
However if your getters\setters do something else than solely changing values like logging\etc then you obviously always need to use them.
It's ok to use either. The point of getters/setters is to provide safe access to fields for clients that don't know about the internals of the class, but the class itself does know about its internals. If the getters/setters do something additional that needs to be done even if they're called from inside the class, call them. Otherwise you can just access fields directly.
If you are just learning OOP, then by all means stick to private members exposed via public methods. This is not to say that public fields are all bad, but to learn which to use when, you must study both approaches in detail.
Within the class private members are almost always accessed directly and this would certainly be the first choice—the whole point of encapsulation is the separation of code within the fence and code outside of it.