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:
soldier.loadGun(15); // calls Gun.load()
soldier.fire(); // calls Gun.fire()
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.
First off, you'd be violating the Law of Demeter by accessing the Gun from outside the Soldier class.
I would consider methods like these instead:
soldier.ArmWeapon(...);
soldier.Attack(...);
This way you could also implement your fist, knife, grenade, baseball bat, laser cat, etc.
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.
Indeed, it depends a lot about how much control you want to have.
To model the real world, you might even want to completely encapsulate the gun object, and just have a soldier.attack() method. The soldier.attack() method would then see whether the soldier was carrying a gun, and what the state of the gun was, and fire or reload it as necessary. Or possibly throw the gun at the target and run away, if insufficient ammunition were present for either operation...
If you expose gun, you allow things beyond the member functions of the Gun, which is probably not a good idea:
soldier.gun = anotherGun; // where did you drop your old gun?
If you use getGun(), the calls look a little ugly, but you can add functions to Gun without modifying Soldier.
If you encapsulate the functions (which I recommend) you can modify the Gun or introduce other (derived) classes of Gun without changing the interface to Soldier.
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.
Provide a "getGun()" or simply "gun()".
Imagine one day you may need to make that method more complex:
Gun* getGun() {
if (!out_of_bullets_) {
return &gun_;
} else {
PullPieceFromAnkle();
return &secret_gun_;
}
}
Also, you may want to provide a const accessor so people can use a const gun on a const soldier:
const Gun &getGun() const { return gun_; }
There's no golden rule that applies 100% of the time. It's really a judgement call depending on your needs.
It depends on how much functionality you want to hide/disallow for the gun from access to the Solider.
If you want to have only read only access to the Gun you could return a const reference to your own member.
If you want to expose only certain functionality you could make wrapper functions. If you don't want the user to try to change Gun settings through the Soldier then make wrapper functions.
Generally though, I see the Gun as it's own object and if you don't mind exposing all of Gun's functionality, and don't mind allow things to be changed through the Soldier object, just make it public.
You probably don't want a copy the gun so if you make a GetGun() method make sure that you aren't returning a copy of the gun.
If you want to keep your code simple then have the soldier responsible for dealing with the gun. Does your other code need to work with the gun directly? Or can a soldier always know how to work/reload his own gun?
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.
return reference-to-const when you can (Effective C++ Item #3).
Prefer consts, enums, and inlines to using hard coded numbers (Item #4)
provide unique naming conventions for your private members to distinguish them from arguments
Use unsigned values where they make sense to move errors to compile time
When const values, like maximums, apply to an entire class. Make them static.
If you plan to inherit, make sure your destructors are virtual
initialize all members to sane defaults
This is how the classes look after that. CodePad
#include <iostream>
#include <string>
#include <stdint.h>
using namespace std;
class Gun
{
public:
Gun() : _bullets(0) {}
virtual ~Gun() {}
void fire() {cout << "bang bang" << endl; _bullets--;}
void load(const uint16_t bullets) {_bullets = bullets;}
const int bullets() const {return _bullets;}
static const uint16_t MAX_BULLETS = 17;
protected:
int _bullets;
};
class Soldier
{
public:
Soldier(const string &name, const Gun &gun) : _name(name), _gun(gun) {}
virtual ~Soldier() {}
const string& name() const;
Gun& gun() {return _gun;}
protected:
string _name;
Gun _gun;
};
int main (int argc, char const *argv[])
{
Gun gun; // initialize
string name("Foo");
Soldier soldier(name, gun);
soldier.gun().load(Gun::MAX_BULLETS);
for(size_t i = 0; i < Gun::MAX_BULLETS; ++i)
{
soldier.gun().fire();
cout << "I have " << soldier.gun().bullets() << " left!" << endl;
}
return 0;
}
Related
I have a top-level class which instantiates sub modules using composition. The user knows that the top class will have these submodules. Is it a good idea to make the submodule objects public members so that the user can call their functions directly?
The alternative seems to be to wrap their function calls which protects the submodules from being made public, but doesn't have any encapsulation benefit since the user needs to specify the submodule anyway.
Here is a top-level class House with submodules kitchen and bathroom.
// Public member objects
class Kitchen {
public:
void turn_on_tap();
int compute_area();
};
class Bathroom {
public:
void turn_on_tap();
int compute_area();
};
class House {
public:
Kitchen kitchen;
Bathroom bathroom;
int compute_area() { return kitchen.compute_area() + bathroom.compute_area(); }
};
//User code:
House house;
house.kitchen.turn_on_tap();
house.bathroom.turn_on_tap();
house.compute_area() // OK
house.bathroom.compute_area(); // may not want user to be able to do this
// Private member objects
class House {
Kitchen kitchen;
Bathroom bathroom;
public:
void turn_on_kitchen_tap() { kitchen.turn_on_tap(); }
void turn_on_bathroom_tap() { bathroom.turn_on_tap(); }
int compute_area() { return kitchen.compute_area() + bathroom.compute_area(); }
};
//User code:
House house;
house.turn_on_kitchen_tap();
house.turn_on_bathroom_tap();
house.compute_area();
I prefer the syntax of the first but it means making the member objects public.
The second approach seems tedious because of the additional functions I have to write to wrap the underlying function calls. And I lose the nice dot hierarchical dereferencing because the user knows (and needs to know) about the underlying hierarchy.
EDIT: But if I make them public, I will expose other backend public functions in Kitchen and Bathroom that I don't necessarily want the user to be aware of. So then I might have to make those private and use "friend" which gets a little ugly.
Added compute_area() to above code.
It depends. If a house is a simple aggregate, i.e:
A valid value of a House is any combination of valid values of Kitchen, and Bathroom. That is to say, there is no House specific invariant to keep.
The individual components handle their own invariants correctly by themselves, and by extension the container's given point No. 1.
The container's member functions are just tiny wrappers around each component, or even just return a reference to a component for modification.
Then yes, a simple struct (for the default public access) is indeed proper. "Encapsulating" here is just an exercise in verbosity. Sometimes the object you need is just a bunch of stuff glued together, with no further logic.
So whether or not it's a good a idea is something you will need to examine for your own application by yourself.
If I have a simple 2 level class hierarchy as, for instance, this one:
// level 1
class Spare_Part{
private:
string name;
double price;
public:
Spare_Part();
string getName() { return name; }
double getPrice() { return price; }
virtual int getQuantity() { return -1; }; // may also define it as pure virtual
};
//level 2
class On_hand : public Spare_Part{
private:
int quantity;
string location;
public:
On_hand();
int getQuantity(){ return quantity; }
};
I want to have access to the member 'quantity' in the class 'On_hand' using a pointer to the base class 'Spare_part', so I made the 'getQuantity' function a virtual one. The code works fine, however, I have a feeling that I shouldn't have a get/set function (even though a virtual one) to access a member that is defined somewhere down the hierarchy. Is this really considered a bad practice that should be avoided by, for example, redesign of the classes?
Edit:The whole hierarchy is a little bit more complex. Alongside the 'On_hand' class there is class for parts available through contracted suppliers. The assumption is that I wouldn't be able to know how many parts are available through the suppliers and that is why 'quantity' is not included in the base class.
In this case, yes, this is bad practice; if it doesn't make sense to call getQuantity on a Spare_Part, it shouldn't compile. It should definitely not just return a flag value.
A redesign of your classes is probably necessary. Polymorphism should be used to model an is-a relationship, but your use is mostly to tag more data onto the class. You should use composition instead, perhaps making a Part_Store class which contains a Spare_Part, the quantity and location.
Let's try sorting things out.
There's nothing wrong in having a base calling its derived class to read a property. There are cases when it's known that every implementation of a base class must have a property, and the base class offers some functionalities that require that property, and that would be the same in all reasonable implementation, except for that property.
In such cases, there's absolutely nothing wrong in doing that.
As an alternative, if you're really sure that property is always going to be implemented with a simple fixed-type variable in any reasonable implementation, you can just add a protected variable to the base class, and let the implementations write to it.
It's all a matter of how much flexibility you need.
In your case, I think your conceptual inheritance model is flawed, which kind of empties your case of any meaning.
You are saying that On_hand derives from Spare_Part, which means, by definition, that every On_hand is a Spare_Part. This sounds weird to me, as being "on hand" sounds more like a quality of the spare part, than a special case of it. Maybe it'd be better to add an optional<On_Hand> to Spare_Part.
Or, even better, I suspect you want something like
struct On_Hand_Info { int quantity; string location; };
std::map<Spare_Part, On_Hand_Info> on_hand;
EDIT
Seen your last updates, maybe you should do something like:
struct IRetrievalInformation {
virtual int getQuantity() const=0;
};
class SparePart{
string name;
double price;
std::unique_ptr<IRetrievalInformation> retinfo;
public:
Spare_Part();
string const& getName() const { return name; }
double getPrice() const { return price; }
IRetrievalInformation const& getRetrievalInformation() const {
assert(retinfo);
return *retinfo;
}
IRetrievalInformation& getRetrievalInformation() {
return const_cast<IRetrievalInformation&>(
const_cast<SparePart const*>(this)->getRetrievalInformation()
);
}
};
class OnHandRetrieval : public IRetrievalInformation {
int quantity;
string location;
public:
On_hand();
int getQuantity() const final override { return quantity; }
};
PS: for God's sake, don't use both camelcase and underscores.
IMO, getters and setters must be considered as a bad practice and even an anti-pattern in almost all cases. The whole point of using OOP is to conceal implementation details (well, not only this, but this is also among others). Getters/setters are intended to expose implementation details, hence it ruins one of OOP principles. In the end, why not using old plain C structs, if you are using getters/setters? In such case, classes don't have any advantages over structs.
Well, there are cases when getters/setters may look good. The point is, there are too many programmers use them as replacement for structs. And the reason usually -- they don't understand how to design application in OOP manner.
In your case you don't need getters/setters. Just think about how you are gonna use this class further. Is it gonna have any extra functionality or just store some data? If so, maybe just use POD structs?
Further reading:
[1] http://www.javaworld.com/article/2073723/core-java/why-getter-and-setter-methods-are-evil.html
[2] http://www.yegor256.com/2014/09/16/getters-and-setters-are-evil.html
[3] http://typicalprogrammer.com/doing-it-wrong-getters-and-setters/
[4] Why use getters and setters?
[5] http://berryllium.nl/2011/02/getters-and-setters-evil-or-necessary-evil/
I had a really long post on this and decided it can be summed up much shorter. Canonically speaking, is it better to include a data member inside of a class as opposed to inheriting it? I found I can implement identical functions either way, but don't really know what caveats I should be aware of.
Code example
#include "KClass.h"
class KPC : public KCharacter {
private:
KClass MyClass;
};
versus
class KClass : public KCharacter {
};
class KPC : public KClass {
};
In the first example, anytime I needed something from the KClass data, I could access it via MyClass->
In the second class, class KPC would just directly access them since it would inherit the data members.
For specifics to my problem I guess I should detail the class' function.
D&D format. Each character has a class which would determine: weapon/armor proficiencies, bonus defenses, special ability i.e. defender has mark.
So to me, it made sense to inherit it. However, is class a more specific PC or is PC a specific kind of class? There are so many PCs in a game that aren't a specific class, actually class should inherit PC on that concept sense it's more 'specialized' form of a PC. So would I want to structure it in a way of KClass : KPC ?
It seemed easier to implement a Has-A at first, but now I'm second guessing it. Hence the reason why I'm here, asking this question.
Generally speaking, composition is better than inheritance. But it depends on what exactly you want to do. For the most part think:
IS A -> inheritance
HAS A -> composition
Inherit when you want/need to extend a base class. If you just need to use another class, just have an instance of it with the other class.
Side note, composition and aggregation are basically the same thing. Conceptually slightly different, in code, the same thing.
It's a matter of design and what you are trying to model. Scott Meyers' Effective C++ will note that public inheritance (the second example) models 'is-a', whereas composition (the first example) models 'is-implemented-in-terms-of' or 'has-a'. So, for your example, you should decide what role KClass is playing and which of these philosophies makes more sense. Just looking at the names KCharacter, KClass, and KPC, it's hard for me to tell their purposes.
It really depends on what you are trying to do. Yes, both achieve mechanically similar things, but the rule is "is-a" or "has-a" for deciding which way to go.
If KPC really "is-a" form of KClass, then you should use inheritance. This means that you are looking to solve a polymorphic problem - you have several items that are similar:
class AeroPlaneBase
{
...
};
class JetPlane : public AeroPlaneBase
{
...
};
class PropellerPlane : public AeroPlaneBase
{
...
};
class GliderPlane : public AeroPlaneBase
{
};
All of these planes can do similar things - but they behave slightly differently, so they need a different class to describe their behaviour.
Now, each plane will have zero or more "engines", so the class may have a "has-a" relationship to a PlaneEngine class. The glider, which is an engineless plane doesn't have any engine, the JetPlane can have 8, perhaps...
Likewise, in a roleplaying game, a player "is-a" Character (which is also the baseclass for Monster and the different derived forms of that), say, but "has-a" relationship with the Weapon class. The Character isn't a type of Weapon, but it has a weapon.
Conceptual
The concept of classes and objects is usually used to model "real" things. But let's put the cart before the horse.
The transfer of the inheritance concept to the real world would be (like others said) an IS A-relation.
A TFT is a screen
A Fox is an Animal
...
The composition is, in contrast, usually considerd as HAS A-relation.
A PC has a CPU
A knife has a blade
...
So if you want to model the latter in object-oriented programming, make use of composition. In case of the former concept, use inheritance.
Examples
Composition > Inheritance
Examples always tend to come naturally to me. So I'll try to illustrate it a bit further. (No encapsulation here, sorry. ;))
Consider motorvehicles, respectively cars. The tend to have an engine, which has a specific sound.
struct Engine
{
void sound (void) const { std::cout << "BROOOM" << std::endl; }
void open_valve (void) { /* ... */ }
};
Engines also can perform certain engine-specific tasks.
Now we can have both specified options to include the engine into a car: inheritance or composition.
struct Car_A : public Engine { };
At the first moment, this seems appropriate. We don't need to reprovide sound() since a car (in the first approximation) just sounds like an engine.
Car_A a_car;
a_car.sound(); // mycar sounds like a car!
But the noise is not very realistic: No tread noise, no air draft. So we can just shadow the underlying method and define:
struct Car_A : public Engine
{
void sound (void) const
{
std::cout << "tread noise + air draft" << std::endl;
Engine::sound();
}
};
We still have a slight problem.
a_car.open_valve(); // ?
The concept of valves is part of the engine but not part of the car but we can use this method on the car.
The car has an engine but it isn't one.
We could switch to private inheritance now but the method would still be present, although not accessible.
Another (less conceptual) issue can be seen when using pointers of the types:
Engine * pointer_to_engine(new Car_A); // works
An engine that actually is a car? "(Suspected) Engines" exhibiting car behaviour and vice versa? Well that doesn't look like the way to do things here.
Let's look at composition instead:
struct Car_B
{
void sound (void) const
{
std::cout << "tread noise + air draft" << std::endl;
engine.sound();
}
void open_door (void) { /* ... */ }
Engine engine;
};
That's how things are supposed to be: A car that has a[n] (member) engine that sounds like an engine and contributes to the sound of the car and no methods are present in the car that are not part of the concept of a car.
Car_B b_car;
b_car.sound(); // still sounds like a car!
b_car.engine.open_valve(); // meaningful for an engine!
Here we have a case where composition is superior.
The "real" situation is modeled.
All concepts keep their validity. (No unintended behaviour.)
Inheritance > Composition
Now we add another Concept in our example: a vehicle.
struct Wheel {};
struct Motorvehicle
{
virtual void sound (void) const { engine.sound(); }
Engine engine;
std::vector<Wheel> wheels;
};
A motorvehicle is driven by an engine, so it knows to emmit engine sound.
However, the abstract vehicle has no clue of how many wheels its concrete objects will have have (motorcycle? car?) or how its shape is formed, so it can't tell anything about tread noise and air draft.
This time we look at composition first (miracle miracle...):
struct Car_C
{
void sound (void) const
{
std::cout << "tread noise + air draft" << std::endl;
vehicle.sound();
}
Motorvehicle vehicle;
};
Looks legit, doesn't it?
Car_C c_car;
c_car.sound(); // correct sound!
c_car.vehicle.sound(); // what the hell is "the vehicle of a car"?
c_car.wheels.... // error the car has no wheels?!
"Pretending" that wheels are part of the car will require us to add an additional function for our car. If we use inheritance instead, this coherency comes from scratch.
struct Car_D
: public Motorvehicle
{
void sound (void) const
{
std::cout << "tread noise + air draft" << std::endl;
Motorvehicle::sound();
}
};
The observable behaviour of Car_D is more like you would expect it to be.
Car_D d_car;
d_car.sound(); // correct sound!
d_car.wheels.[...] // valid, our car has wheels!
Conclusion
The consideration, whether to use inheritance or composition is not always as easy as in my examples but you should try to weight up and choose the concept that performas better in reflecting the desired behaviour.
If the designated base class describes an abstract generalization of the derived class, this is a good hint for inheritance.
This is really a question of good form/best practices. I use structs in C++ to form objects that are designed to basically hold data, rather than making a class with a ton of accessor methods that do nothing but get/set the values. For example:
struct Person {
std::string name;
DateObject dob;
(...)
};
If you imagine 20 more variables there, writing this as a class with private members and 40-something accessors is a pain to manage and seems wasteful to me.
Sometimes though, I might need to also add some sort of minimal functionality to the data. In the example, say I also sometimes need the age, based on dob:
struct Person {
std::string name;
DateObject dob;
(...)
int age() {return calculated age from dob;}
}
Of course for any complex functionality I would make a class, but for just a simple functionality like this, is this "bad design"? If I do use a class, is it bad form to keep the data variables as public class members, or do I just need to accept it and make classes with a bunch of accessor methods? I understand the differences between classes and structs, I'm just asking about best practices.
I think there are two important design principles to consider here:
Hide a class's representation through an interface if there is some invariant on that class.
A class has an invariant when there is such thing as an invalid state for that class. The class should maintain its invariant at all times.
Consider a Point type that represents a 2D geometric point. This should just be a struct with public x and y data members. There is no such thing as an invalid point. Every combination of x and y values is perfectly fine.
In the case of a Person, whether it has invariants depends entirely on the problem at hand. Do you consider such things as an empty name as a valid name? Can the Person have any date of birth? For your case, I think the answer is yes and your class should keep the members public.
See: Classes Should Enforce Invariants
Non-friend non-member functions improve encapsulation.
There's no reason your age function should be implemented as a member function. The result of age can be calculated using the public interface of Person, so it has no reason to be a member function. Place it in the same namespace as Person so that it is found by argument-dependent lookup. Functions found by ADL are part of the interface of that class; they just don't have access to private data.
If you did make it a member function and one day introduced some private state to Person, you would have an unnecessary dependency. Suddenly age has more access to data than it needs.
See: How Non-Member Functions Improve Encapsulation
So here's how I would implement it:
struct Person {
std::string name;
DateObject dob;
};
int age(const Person& person) {
return calculated age from person.dob;
}
In C++, Structs are classes, with the only difference (that I can think of, at least) being that in Structs members are public by default, but in classes they are private. This means it is perfectly acceptable to use Structs as you are - this article explains it well.
In C++, the only difference between structs and classes are that structs are publicly visibly by default. A good guideline is to use structs as plain-old-data (POD) that only hold data and use classes for when more functionality (member functions) is required.
You may still be wondering whether to just have public variables in the class or use member functions; consider the following scenario.
Let's say you have a class A that has a function GetSomeVariable that is merely a getter for a private variable:
class A
{
double _someVariable;
public:
double GetSomeVariable() { return _someVariable; }
};
What if, twenty years down the line, the meaning of that variable changes, and you have to, let's say, multiply it by 0.5? When using a getter, it is simple; just return the variable multiplied by 0.5:
double GetSomeVariable() { return 0.5*_someVariable; }
By doing this, you allow for easy maintainability and allow for easy modification.
If you want some data holder then prefer struct without any get/set methods.
If there is more to it, as in this case "Person".
It models real world entity,
Has definite state and behaviour,
Interacts with external world,
Exhibits simple/complex relationship with other entities,
it may evolve overtime,
then it is a perfect candidate for a class.
"Use a struct only for passive objects that carry data; everything else is a class."
say google guidlines, I do it this way and find it a good rule. Beside that I think you can define your own pragmatics, or deviate from this rule if it really makes sense.
I don't want to sparkle a holy war here; I usually differentiate it in this way:
For POD objects (i.e., data-only, without exposed behavior) declare the internals public and access them directly. Usage of struct keyword is convenient here and also serves as a hint of the object usage.
For non-POD objects declare the internals private and define public getters/setters. Usage of class keyword is more natural in these cases.
For just clearing the confusion for some! And easy picking! Here some points!
In struct! you can have encapsulation and visibility operators (make private or public)! Just like you do with classes!
So the statement that some say or you may find online that say: one of the differences is that structures have no visibility operator and ability to hide data, is wrong!
You can have methods just like in classes!
Run the code bellow! And you can check it compiles all well! And run all well! And the whole struct work just like class!
Mainly the difference is just in the defaulting of the visibility mode!
Structures have it public! Classes privates by default!
#include<iostream>
#include<string>
using namespace std;
int main(int argv, char * argc[]) {
struct {
private:
bool _iamSuperPrivate = true;
void _sayHallo() {
cout << "Hallo mein Bruder!" << endl;
}
public:
string helloAddress = "";
void sayHellow() {
cout << "Hellow!" << endl;
if (this->helloAddress != "") {
cout << this->helloAddress << endl;
}
this->_sayHallo();
}
bool isSuperPrivateWorking() {
return this->_iamSuperPrivate;
}
} testStruct;
testStruct.helloAddress = "my Friend!";
testStruct.sayHellow();
if (testStruct.isSuperPrivateWorking()) {
cout << "Super private is working all well!" << endl;
} else {
cout << "Super private not working LOL !!!" << endl;
}
return 0;
}
In memory they are the same!
I didn't check myself! But some say if you make the same thing! The compiled assembly code will come the same between a struct and a class! (to be checked!)
Take any class and change the name to typedef struct ! You'll see that the code will still works the same!
class Client {
}
Client client(...);
=>
typedef struct Client {
....
} Client;
Client client(...);
If you do that all will works the same! At least i know that does in gcc!
YOu can test! In your platform!
//////////////////////////////////////////////////////////////////////////////////////////
// Note: Automatically generate getter and setter
template<typename T>
class Wrap {
public:
...
const T& operator()() const
{
return m_element;
}
void operator()(const T& element)
{
m_element = element;
}
...
private:
T m_element;
};
// Pro: The container may have more than 20 different member variables.
// Each goes with a simple getter and setter for now. Due to the Wrap
// class, we don't have to add getter and setter for any new variable
// Con: Since this is a public API interface, if the user directly adopt the
// Wrap class, it is difficult for any future improvement. Based on this design,
// we cannot make Wrap private embeded class of Container since the user needs to
// access those public member variables of Container
class Container
{
public:
Wrap<int> Age;
Wrap<double> Balance;
...
};
//////////////////////////////////////////////////////////////////////////////////////////
// Con: For each different member variable, we have to add getter and setter methods
// which will be a problem considering if you have 20 member variables.
// Pro:
// By using PIMPL pattern, we can make the interface more robust for future improvement
// without breaking our client's code.
class PimplClass
{
public:
int Age() const;
PimplClass& Age(int _age);
double Balance() const;
PimplClass& Balance(double _balance);
private:
Pimpl* m_data; // hide internal data structure from the public API interface
};
//////////////////////////////////////////////////////////////////////////////////////////
Question> Is there a better design that I can combine both auto getter+setter generation and PIMPL design pattern
into this public API interface?
Thank you
// ****** Updated ************
After reading all those articles, I am convinced that getter and setter are evil. Now the question comes to how to avoid them all together.
For example,
class Bond
{
...
private:
long m_lPrice;
std::string m_strBondName;
int m_iVolume;
}
Give the above class Bond which includes three member variables, without using getter and setter, how does client get the price, name, or volume of an bond object?
This is the another example of getter/setter in Qt4.
Here's the improved QProgressBar API:
class QProgressBar : public QWidget
{
...
public:
void setMinimum(int minimum);
int minimum() const;
void setMaximum(int maximum);
int maximum() const;
void setRange(int minimum, int maximum);
int value() const;
virtual QString text() const;
void setTextVisible(bool visible);
bool isTextVisible() const;
Qt::Alignment alignment() const;
void setAlignment(Qt::Alignment alignment);
public slots:
void reset();
void setValue(int value);
signals:
void valueChanged(int value);
...
};
Thank you
Getters and setters are there so that you can "grab" into an object's guts and fiddle with its innards. That should make your alarm bells ring very loudly. For a well-designed class, you do not have to dig through its guts, since it lets you do everything you need to do through its interface without leaking any of its implementation details through the abstraction.
Design a class from the point of view of a user of the class ("if I have a qrxl object, I would need to make it wrgl() like this, and I also need to pass it a lrxl object occasionally, which it then uses to do frgl()"), rather than from the point of view of the implementer who needs to somehow organize his data and algorithms into useful (for him!) chunks. ("Let's just put this Johnny over here into that class, because that's where it is close to where I need it for implementing the xrxl() algorithm.")
I think in this regard Java has done a huge disservice to humanity in that it requires you to put everything into some class, even if this is against how you actually visualize your design in your head, and even if you are not (yet) thinking object-oriented. This seems to have made a design style en vogue where programmers just stuff everything into some class somewhere because "that's the way it's done."
In lots of Java code I've seen the underlying programming style is actually Structured Programming (basically "collect your data in useful chunks, and pass those to your algorithms", as done in C or Pascal), rather than Object-oriented Programming. Just because you replace struct/record by class and make the data members in this chunk only accessible through getters and setters, this doesn't mean you are doing object-oriented programming.1 This is what the author of that wonderful short paper calls pseudo classes
From what little I know about Qt, its design is also a pretty good example for a pretty bad example, with everything allocated on the heap, handed around in naked pointers, and employing the quasi-class school of design.
Give the above class Bond which includes three member variables, without using getter and setter, how does client get the price, name, or volume of an bond object?
This is the wrong question. The right question is why would a user need to get at those values? If you need to get at them manually, then Bond isn't high enough an abstraction for OO design, it's a mere C-style struct where you throw together all the data you need in one place. Ask yourself:
What would a user of a Bond want to do with such an object? How can I make the class support those operations without users having to grab into it and fiddle with its guts? How can I make the classes that interact with Bond do this? Can I pass them Bond objects, rather than price, name, or volume of an bond object?
Yes, sometimes you have to have just a bond's price in order to display it, and if that's the case, then Bond will need to support a getter function for the price, and that's Ok then. But you could still pass a Bond object to your BondPriceTable's displayBonds() function, and let that decide whether it wants to just grab the name and the price and throw that at the screen or display more values. There is no need to extract name and price manually and pass those to a display() function.
1 That's especially appalling because Java aficionados so often look down at C++ for not being "purely OO".