Worth Get() and Set() in games ?

Started by
30 comments, last by AndyTX 19 years, 9 months ago
Well, that's all well and good, but unless the time calculated by that timer is just for show, eventually you're going to need to read it. Hence, get(). And at some point you may wish to set it in an unusual way, hence, set(). Now, if you're using both, multiple times, in one function, alarm bells should go off.

Plus, OOP gurus always seem to forget about the inability to add run-time extension. C++ is limited that way. If you're using someone else's library of objects, you can't just subclass an object that they use internally and change it. You can't just say "boy, I wish I had a 'next week' method. I think I'll add one". If there isn't one, you code it externally, functional-style.

In Python you can add new methods to an existing class, but its not good policy, as it could conflict with other methods added by other modules being coded by other people.

My basic opinion is this: there's another part of the coding world that most languages haven't perfected, and that is interoperability. When you use someone else's code, you lose a lot of freedom. Scripting languages give some back, but its usually in the form of "happy accidents" like I described with Python (setting class.method = mynewmethod).
-- Single player is masturbation.
Advertisement
If you use C++ Builder or the new VS.net (2005) you have "properties" like in other languages... they can be very handy in situations like this. In either case you can always invisably change a field to a property and introduce logic without changing any other code, which can come in really handy :)

Without them though, you can still use get and set methods. The obvious advantage is that of being able to change things later when your classes become more complicated. An example could be a common "IsDone"-type function on - lets say - a GUI window. Initially it might simply read like:
bool IsDone() const { return (State == Closed); }

Although later when you add spiffy animations and stuff you might alter it to be:
bool IsDone() const { return (State == Closed && AnimDone()); }

Simple example really, but it comes up pretty often.

Regarding set methods you really do need to look into what others have mentioned... the idea of encapsulation is that outside objects should not be messing with the "data" portions of other objects. Things like "SetAxisRange" on a Joystick object make perfect sense for example (and would contain more complicated calls to the input API for example), while directly changing internal counters and lists for example are probably an indication of trouble.

Remember that you want to keep the "binding" between your objects as small as possible... if you change something in your one object, you want to at most change a few bodies of your get methods... you should *not* have to go changing much code in other objects.

That said, when you feel like making something a public member it is probably better to use a property (if available), or get and set methods. Again I'm not one to be preaching that since I certainly break that rule from time to time (although I don't end up using many public member variables), but I see no disadvantage to always using getters and setters in general. If you have access to properties, you have no excuse :)
Quote:Original post by Pxtl
Well, that's all well and good, but unless the time calculated by that timer is just for show, eventually you're going to need to read it. Hence, get().


Hi Pxtl, thanks for responding. The Time class would of course have whatever it needed to be a useful class.

The point was that we moved

from:
having some object handling an integer member of another object and doing all the calculations itself

to:
making a function which passed that onto another object which was better at doing all the messy stuff.

The benefits are that you are communicating between objects in terms of what you want them to do for you rather than doing it yourself and telling them what values they should be.

I was initially going to say the getTime function would return a Time object instead of the integer, which we could then call a function addWeek and then pass it back with obj.setTime(time);

But I went the next step of further removing any need for the user to know that the class was using a Time object to keep track of what week it was. All the user wants to do is advance it a week. It could be an integer, it could be a Time object. Who cares? I just want to advance a week.

Get and Set would probably be on the Time object. But the initial objects I was talking about are no longer passing around integers with Get and Set or doing calculations either. The Get, Set and the integer no longer exist.
I agree completely with petewood. If you have a plethora of Get/Set functions operating on primitives (and you use them often), then more than likely you should abstract those operations away into a higher-level object.

Operations on objects convey much more information to people reading the code than calls to Get/Set functions. And, more often than not when you need to actually get at the underlying data, you need to perform some sort of operation. That operation also should be abstracted away into its own function or object.

At your lowest level, yes, you are going to probably have classes that rely on Get/Set methods (or, you'll just have simple structs), but that's where they belong, at the lowest level. People browsing the "main" parts of your program shouldn't be seeing those low level details.
"Is life so dear, or peace so sweet, as to be purchased at the price of chains and slavery?" - Patrick Henry
Personally I've been doing it like this lately:
class Foo{...public:   Bar &       bar()      {         return mBar;      };   const Bar &      bar()      const      {         return mBar;      };private:   Bar mBar}


I used to call them getVar, setVar but I figure the compiler is smart enough to remove the references where it would mean a lot of overhead. This also allows cleaner code in my experience along with the benefit of having a custom function called for each get/set. The code will look like this:

Foo a;a.bar() = 12:Bar b = a.bar() + 200;


Works well for me and I've not noticed any loss of speed.
OK, using C# I have this situation.
public class DataHolder{   private int _aValue;   public int aValue   {     set     {       _aValue = value;     }   }   public void GetMyData()   {     ...        }}


Now, 'GetMyData' needs to go to a database in order to get the value of '_aValue'. However, I want to keep 'DataHolder' clean and put all the boring database access code in a DAL (data access layer) .

So how does one get the DAL to set the property in 'GetMyData' without there being a 'set' method or a property at all?

BD.
Easiest would be to use a delegate to set the variable. You can turn a private function into a publicly callable delegate.

If the DAL is synchronous, you could also pass an inOut parameter.
enum Bool { True, False, FileNotFound };
Wait... VC++2005 has properties?
Not giving is not stealing.
Quote:Original post by thedevdan
Wait... VC++2005 has properties?


Nothing new, so does archaic VC++ 6.0

class foo{public:	void setInt(int y) { value = y; }	int getInt() { return value; }	__declspec(property(get = getInt, put = setInt)) int val;private:	int value;};//foo bar;bar.val = 4;cout << bar.val << endl;
A while ago, I tried to create properties using operator overloading.
When you create a nested subclass for every property and overload its assignment and say int operator you could create an effect quite similar to properties.
I only had a problem in printf statements, because the int operator wasn't called. You had to manually insert an cast, because the prototype of printf doesn't expect an int value. printf(char *,...), or something similar.

Does anyone have an idea how you could circumvent this? Is there a way to enforce the use of the int operator?
Any idear, if this approach will lead to other problems?

This topic is closed to new replies.

Advertisement