OO Concepts: Objects & Classes

Objects

Interacting with Objects

Objects are miniature programs that are complete with their own private copy of all internal data. The designer of the object decides exactly how the object can be used. This can be done independently of the application in which it is used Properly designed and tested objects are robust and can be reused in new applications. The secret is in the way a user interacts with an object.

The user sends a message to an object and gets a reply. The message may result in the object changing state. The designer of the object decides what messages are allowed and how the object will react and so can test it before the user gets hold of it.

In this series of OO concept talks we shall illustrate some of the concepts by developing a series of track objects. We can make a start on this now, by deciding a few fundamentals about such objects. Clearly one of the properties of a track is its energy. If we have a track called MyTrack, then we could ask it for its energy using the assignment:-

energy = MyTrack.GetEnergy();
There is quite a lot to take in here:-
  1. First comes MyTrack -the name, or identifier of the object MyObject. Objects have names just like variables in FORTRAN. Identifiers consist of alphanumeric and underscore, although underscore is not popular in ROOT, they use the character heavily for special names so, by not using the character, potential conflicts are avoided. To break up compound name, capitalisation of the first letter is preferred. This brings up another point that a FORTRAN programmer had better get used to: variable identifiers are case sensitive in C++; MyTrack is not the same as mytrack!!
  2. Next comes a dot. This is the member selection operator and is use to indicate which member (i.e. which bit) of the object you want to deal with.
  3. Finally comes GetEnergy() - which looks a bit like a function only there isn't anything in it argument list. The reason is looks like a function is because that's exactly what it is. Strictly it should be called a member function. This brings us to another fundamental point: Sending a message to an object means calling one of its member functions. The reason that there isn't an argument list is that there is no need to qualify this particular message; we just want the track's energy. Typically an object will have a number of member functions that start "Get" that simply return some information about its state. These are often referred to collectively as "getters". Often there will be a parallel series of functions that start "Set", that change them. So we might change the state of our track by:-
    MyTrack.SetEnergy(energy);
    
    Now we have to supply additional information, via the argument list, the energy we want to set.

No Free Lunches

Just to underline a very important point, if we can change the energy of the track, its because the designer of the track object permits it, not because the user of the track object thought up a new way of using the software. When software development breaks previously tested code it is often because it is being used in ways that were not anticipated when it was written ("Oh, I never expected the code to be used like that"). So robustness come from the fact that the object designer has to look beyond the current application to see the object as an entire concept, independent of any one application. This forces a better design but at the price of more work - there are no free lunches!

Beyond FORTRAN

To a FORTRAN programmer, this may seem to be rather like a subroutine with local data and a set of entries points, one for each message. This is not a bad model for a single object, but OO allows two fundamental changes:-

Class

A Module Factory

A class is rather like an object factory. Each time a new object is required it is created using the information in the class. The class holds the code shared by all of its objects. It also contains details of an object's internal data and this used to reserve space and initialise it when an object is brought into existence, a process called instantiation'.

Continuing with our track object, lets look at a (slightly incomplete) definition of a track class. To flesh out the track model a little more we will add both mass and momentum to the model:-

class Track {

  Float_t fEnergy;
  Float_t fMass;
  Float_t fMomentum;

  Float_t GetEnergy() { 
    return fEnergy; 
  }

  void  SetEnergy( Float_t energy ) {
    fEnergy = energy;
    fMomentum = sqrt( fEnergy*fEnergy - fMass*fMass );
  }

};
We will pick this apart, statement by statement.

O.K., now we have our object factory, so lets build some objects:-