|< Free Open Study >|
8.4 Metaclasses à la C++
The object-oriented designer may hear the occasional C++ programmer mutter something about metaclasses. I have stated that the C++ language does not support the notion of metaclass, so what is he or she discussing? Again, in the object-oriented community, one must be very careful with vocabulary. When C++ programmers use the term "metaclass," they are referring to the template construct in C++. The relationship between the template construct in C++ and metaclasses can be best summarized in the following statement.
Metaclasses are traditionally a place where class-specific data and behavior are declared/defined/stored. The notion of templates in C++ came about due to a problem often encountered in strongly typed object-oriented languages. Consider the case where a designer wants a list of dogs called x, a list of airplanes called y, and a list of meals called z. What are the differences between the classes Doglist, Airplane-list, and Meallist? Upon inspection, the three classes differ only on the type of data stored in the list. The algorithms of the three lists are exactly the same. If fact, the code is identical except for the name of the type. Unfortunately, in a strongly typed language, the different type name is enough to require a whole new class definition along with all of its methods. Many developers considered this a waste of code and looked for a better solution. A common approach was to create one list class, called ListOfAnything. They then made the Dog, Airplane, and Meal classes inherit from the class Anything so that they would be allowed in the list (see Figure 8.3). This effectively turned C++ into a weakly typed language for that portion of their application.
While this solution will work, not all applications can use weak type checking at this point in the application. Our original requirements wanted the object x to be a list of dogs, y to be a list of airplanes, and z to be a list of meals. In this solution, the objects x, y, and z are all lists of anything, but by convention x has only dogs in it, y only airplanes, and z only meals. The obvious danger of programming by convention means that it is possible to accidentally put a dog onto the list object y. The control tower then accidentally tries to fly the dog off of a runway. Likewise, people may order a meal at a restaurant and accidentally get an airplane or dog on their plate. The whole point of strong type checking is to catch these errors at compile time, not at runtime.
The developers unhappy with the weak type-checking solution turned to C++'s preprocessor and created elaborate schemes to use it for creating the notion of a parameterized type. They were thwarted by the sheer ugliness of a macro spanning several hundred lines as well as many preprocessor's annoying habit of limiting the macro buffer size to some value like 4K. This implied that a class, with all of its messages and method definitions, had to be described in fewer than 4,000 characters. This was certainly not a good solution either.
Stroustrup's answer to the demand for easy parameterization of classes, maintaining the strong type checking inherent in C++, was the template mechanism. Templates are a language-level facility that uses one description to describe a family of classes. The relationship between the classes being captured in the template abstraction is that they differ on some data type or types that can be provided at compile time by the developer. Our solution to the list of dogs, airplanes, and meals problem posed above is to create a template called "list of your favorite data type." The list template is described with a formal parameter that takes the place of the data to be stored in the list (see Figure 8.4). The corresponding actual parameters are provided at compile time by the developer defining the objects x, y, and z. The template instantiates a new class whenever a new actual parameter is introduced. Since templates instantiate classes, they capture class-specific data and behaviors and therefore are technically metaclasses. However, the true notion of metaclass extends beyond the notion of templates to imply the capture of any class-specific data and behavior, not just the abstractions that templates cover.
|< Free Open Study >|