Here is my code:
class Soldier {
public:
Soldier(const string &name, const Gun &gun);
string getName();
private:
Gun gun;
string name;
};
class Gun {
public:
void fire();
void load(int bullets);
int getBullets();
private:
int bullets;
}
I need to call all the member functions of Gun over a Soldier object. Something like:
soldier.gun.fire();
or
soldier.getGun().load(15);
So which one is a better design? Hiding the gun object as a private member and access it with getGun() function. Or making it a public member? Or I can encapsulate all these functions would make the implementation harder:
soldier.loadGun(15); // calls Gun.load()
soldier.fire(); // calls Gun.fire()
So which one do you think is the best?
I would say go with your second option:
Initially it's more work, but as the system gets more complex, you may find that a soldier will want to do other things before and after firing their gun (maybe check if they have enough ammo and then scream "Die suckers!!" before firing, and mutter "that's gotta hurt" after, and check to see if they need a reload). It also hides from the users of the Soldier class the unnecessary details of how exactly the gun is being fired.
Usually my decision is based on the nature of the container class (in this case, Soldier). Either it is entirely a POD or is not. If it's not a POD, I make all data members private and provide accessor methods. The class is a POD only if it has no invariants (i.e. there is no way an external actor can make its state inconsistent by modifying its members). Your soldier class looks more like a non-POD to me, so I would go to the accessor method option. If it would return a const reference or a regular reference is your own decision, based on the behaviour of fire() and the other methods (if they modify gun's state or not).
BTW, Bjarne Stroustrup talks a little about this issue in his site: http://www.artima.com/intv/goldilocks3.html
A sidenote: I know that's not precisely what you asked, but I'd advice you to also consider the many mentions made in other answers to the law of Demeter: to expose action methods (that act on gun) instead of the entire gun object via a getter method. Since the soldier "has" the gun (it is in his hand and he pulls the trigger), it seems more natural to me that the other actors "ask" the soldier to fire. I know this may be tedious if gun has many methods to act on, but maybe also these could be grouped in more high-level actions that the soldier exposes.
Encapsulate the functions to provide a consistent UI even if you later change the logic. Naming conventions are up to you, but I normally don't use "getFoo()", but just "foo()" as accessors and "setFoo()" as setters.
This is how the classes look after that. CodePad
Provide a "getGun()" or simply "gun()".
Imagine one day you may need to make that method more complex:
Also, you may want to provide a const accessor so people can use a const gun on a const soldier:
The Law of Demeter would say to encapsulate the functions.
http://en.wikipedia.org/wiki/Law_of_Demeter
This way, if you want some type of interaction between the soldier and the gun, you have a space to insert the code.
Edit: Found the relevant article from the Wikipedia link: http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-boy/demeter.pdf The paperboy example is very, very similar to the soldier example you post.
First off, you'd be violating the Law of Demeter by accessing the
Gun
from outside theSoldier
class.I would consider methods like these instead:
This way you could also implement your fist, knife, grenade, baseball bat, laser cat, etc.