views:

247

answers:

5

So I've spent some time thinking about this and been all over google looking for a 'solution' (the solution is most likely a matter of preference, but I'm unsure about this). Below is the problem I have, but the problem can be applied to a lot of situations regarding composition.

I have a class, Colour, containing the members of red, green, blue and alpha. Each of these have a set and get member funtion. Simple enough.

class Colour
{
    public:
        float getRed();
        void setRed(float);
        float getGreen();
        void setGreen(float);
        ...
    private:
        float red;
        float green;
        ...
};

I will use this class within other classes to dictate their colour, for example (omitting the constructor and destructor for brevity):

class ColourableObject
{
    private:
        Colour colour;
};

Now my problem is this: How would this ColourableObject class best access this Colour object? Would it be best to retreive the Colour object to access its member functions directly, like so:

class ColourableObject
{
    public:
        Colour& getColour();
    private:
        Colour colour;
};

Or, would it be better to give the ColourableObject class its own set and get functions for colour, in which act upon the Colour object, like so:

class ColourableObject
{
    public:
        float getRed();
        void setRed(float);
        ...
    private:
        Colour colour;
};

To me, the former is the most logical as it would save a lot of trouble adding functionality to each class that requires this Colour object by simply acting directly upon this Colour object.

However, isn't the latter more susceptible for changes to the ColourableObject class? Not to mention that colourableObject.getColour().setRed(x) doesn't seem too natural to me, as the get and set clash with each other.

I probably have the wrong approach entirely. I'm relatively new to C++, so I'm willing to learn! So the question is, should I use the former method, latter method, or an entirely different method?

+2  A: 

Not to directly answer your question, but I would get rid of all the setters (usually a bad sign to have setters in any case), and use a constructor:

Color c = Color( 123, 17, 77 );

where the three constructor parameters are the RGB values.

anon
I will be using constructors, of course. I omitted them for brevity, though I should have added them for clarity, I apologize. The problem will arise when I need to retrieve or change the RGBA values over the lifetime of the Colour object, which is what the question relates to.Sorry for that inconvenience, and thank you for the response.
Charlie Wilkinson
My point is that you should change all three RGB values at once, and the easiest way to do that is by using a constructor to create a new Color value.
anon
I see. Well as I commented on Shmoopty's answer below, I considered this. I wanted to try and avoid changing all values when I only needed to change one. I will most likely use this solution. Thank you very much everyone for your replies, much appreciated.
Charlie Wilkinson
@Charlie Thanks for being polite, but here on StackOverflow in general we don't say "thankyou" to every comment or answer. Just upvote the answers you find useful, and remember to accept the one you find most useful.
anon
+1  A: 

I probably would recreate your class in case you may need to add other colors like Orange, Purple, Cyan, or Crayola's new Smooky Applewood!

Sort of like a base color class and act upon that base class by introducing a new color. That way it does not matter which color you are dealing with. It's all a black box. Also that will answer your second question as because it doesn't matter which color it is you do not have to redefine your setColor and getColor name methods. They would not need to know or care what color you are referring to.

I think Code Complete (the book) had a section to be a bit leary about seeing classes that have too many get/set methods. It usually boils down to the wrong way of doing things.

JonH
+1  A: 

Your use of getters and setters in this case don't make a lot of sense. You can just as well get away with making the float members of Colour public. Unless you need to do validation or manipulation of more than one private member, just go ahead and make those public, and create a constructor to initialize Colour apprpriately.

As to the ColourableObject, the question you should be asking is: Will other, unrelated classes need access to the object's Colour member? Will they need to make changes to it? If the answer to either of those is "no," I would say that you should not have any kind of getter or setter on that object at all. Otherwise, again, unless you need to do validation or additional state changes, just make the Colour public.

greyfade
Other classes may need to access ColourableObject, such as if ColourableObject is a child of, say, ColourableObjectStorage, which has functions that may wish to change the colour of it's child.As mentioned though, this problem is not directly related to this. It is a problem related to any kind of composition similar to this. I have read all answers on this page, and I have a good idea of how I should handle these problems. Thank you for your response.
Charlie Wilkinson
+1  A: 

The DRY principle supports your first option, providing access to the Colour object.

Furthermore, you may wish to change

    Colour& getColour();

to

    const Colour& getColour();
    void setColour( const Colour& );

...as that will ensure that your ColourableObject will always know when its colour has changed.

Shmoopty
This works well with Colour being immutable.
Steven Sudit
I was actually considering this. I did, however, shrug it off as it seemed like wasted processing power to create a whole new object for changing a single value. For example, I want to change the red value, and I'm required to re-construct all RGBA values.I forgot about writing this consideration in the question, I may consider it, thank you for the response.
Charlie Wilkinson
@Charlie Wilkinson: regardless of the approach you take, try not to get caught up in reducing processing power. Any program can be incrementally optimized until the end of time. It will only be known at the end of your project whether any optimization is needed in the first place.
Shmoopty
@Charlie Wilkinson: Shmoopty has a point here. If you want maximum speed, make Colour an immutable struct that stores just a 32-bit value (for R,G,B,a). Then copying the entire instance will be as cheap as setting any one property.
Steven Sudit
A: 

Personally, I'd prefer dropping the "get" part, in the case of Colorable's member:

colorableObject.Color().setRed(1.0f);

This is, as you said, entirely personal preference (as is the spelling! :) but this way, to me it looks like a "property", rather than a getter/setter method.

mos