Overriding Constructors

From MorphOS Library

Revision as of 11:53, 4 January 2011 by Krashan (talk | contribs) (Contents.)

Grzegorz Kraszewski


An object constructor (OM_NEW() method), takes the same message structure opSet as OM_SET() method. The message contains ops_AttrList field, being a pointer to a taglist containing initial object's attributes. Implementation of a constructor for an object not chaving child objects is simple. The superclass constructor is called first, then, if it succeeds, the constuructor initializes object instance data, allocates resources needed and sets initial values of attributes from tags passed via ops_AttrList.

A rule of thumb when overriding constructor is to never leave a half-constructed object. The counstructor should either return a fully constructed object, or fail completely, freeing all succesfully obtained resources. It is important if the object obtains more than one resource and any of resource allocation may fail (for example allocating a big chunk of memory or opening a file). An example implementation below obtains three resources: A, B and C:

IPTR MyClassNew(Class *cl, Object *obj, struct opSet *msg)
{  
  if (obj = DoSuperMethodA(cl, obj, (Msg)msg))
  {
    struct MyClassData *d = (struct MyClassData*)INST_DATA(cl, obj);

    if ((d->ResourceA = ObtainResourceA()
     && (d->ResourceB = ObtainResourceB()
     && (d->ResourceC = ObtainResourceC())
    {
      return (IPTR)obj;    /* success */
    }
    else CoerceMethod(cl, obj, OM_DISPOSE);
  }
  return NULL;
}

If the object destructor frees resources A, B and C (which would be logical considering the constructor allocates them), the cleanup job may be delegated to the destructor. It requires however, that the destructor must be prepared for destruction of not fully constructed object. It can't assume all three resources have been allocated, so it should check every resource pointer against NULL before calling a freeing function. The desctructor also takes care of calling a superclass destructor when resources are freed. See Overloading Destructors for a destructor example code and explanation.

The only question remaining is what CoerceMethod() does and why it is used instead of a plain DoMethod()? The CoerceMethod() call works exactly the same as DoMethod(), but performs method coercion by forced call to the dispatcher of the class specified as the first argument instead of the dispatcher of the object's true class. It makes a difference, when the class in question is later subclassed. The flowchart below explains the problem: