4 Getting ready to write your clientTop6 Accessing the DDS object5 Subclassing the data types

5 Subclassing the data types

The DAP defines a data type hierarchy as the core of its data model. This collection of data types includes scalar, vector and constructor types. Most of the types are available in all modern programming languages with the exceptions being Url, Sequence and Grid. In the DAP library, the class BaseType is the root of the data type tree.

5.1 A quick review of the data types supported by the DAP

The DAP supports the common scalar data types such as Byte, 16- and 32-bit signed and unsigned integers, and 32- and 64-bit floating point numbers. The DAP also supports Strings and Urls as basic scalar types. The DAP includes Arrays of unlimited size and dimensionality. The DAP also supports three type-constructors: Structure, Sequence and Grid. A Structure on the DAP mimics a struct in C. A Sequence is a table-like data structure inherited from the JGOFS data system. It can be used to hold information that might be stored in relational databases or tables, either flat or hierarchical. The JGOFS, FreeForm and HDF servers all use the Sequence data type. Lastly, the Grid data type is used to bind an array to a group of map vectors, single dimension arrays that provide non-integral values for the indexes of the array. The most typical use of a Grid is to provide latitude and longitude registration for some georeferenced array data (e.g., a projected satellite image). The DAP does not have a pointer data type, but in some cases the Url data type can be used as a pointer to variables between files. More information about the DAP's data type hierarchy is given in the Programmer's Guide.

5.2 Creating the subclasses

When you build a DAP client, you must create a collection of data type subclasses. That is each of the leaf classes in the preceding class diagram must be subclassed by your client. This is pretty easy since a good bit of the work is rote.

First we'll illustrate the parts that are mechanical. Here's an example from the C++ Matlab client. The class is the Byte class. In the case of the matlab client, this class doesn't do anything beyond the bare minimum, so it's a good starting point:

Byte *
NewByte(const string &n)
{
    return new ClientByte(n);
}

BaseType *
ClientByte::ptr_duplicate()
{
    return new ClientByte(*this);
}

bool
ClientByte::read(const string &)
{
  throw InternalErr(__FILE__, __LINE__, "Called unimplemented read method");
}

To create a child of any of the data type leaf classes, you must define three methods and one function. Let's talk about the function first. The function NewByte is what Meyers[2] calls a virtual constructor. It's similar to a low-budget factory class ("low-budget" because it's not a class). This function is used at various places in the DAP library when it need to create instances of Byte without knowing in advance the dynamic type of the object that actually will be created. If all this sounds a little weird, just remember that your Byte, Int16, ..., Grid classes -- whatever they may be called -- must all contain an implementation of this function and each should all return a pointer to an instance of the appropriate child class. These functions will be used by the library to create instance of the classes you have defined when writing your server. In this case of the example Matlab server, it's an instance of the MATByte class. If you look in the files for the Matlab server, you'll see that the function NewGrid returns a pointer to a new MATGrid, and so on.

Second, a constructor must be implemented and should take the name of the variable as its sole argument.

Third, your child classes should also define the ptr_duplicate() method. This method returns a pointer to a new instance of an object in the same class. Occasionally, in the DAP library, objects are declared with pointers specified as BaseType *. If the new operator was used to copy such an object, the copied object would be an instance of BaseType (the static type of the object) not the type of the thing referenced (the dynamic type)4. By using the ptr_duplicate() method the DAP library is sure that when it copies an object, it's getting an instance of the subclass defined by your server.

Unlike the case where you are subclassing the DAP variable classes to build a server, there's no need to implement read() when building a client. The classes contain a default implementation od read() that throws InternalErr if it is ever called (which no simple client should ever do.5


James Gallagher <jgallagher@gso.uri.edu>, 2004/04/24, Revision: 1.10

4 Getting ready to write your clientTop6 Accessing the DDS object5 Subclassing the data types