3.5. Designing an Abstract Base Class

In its design, an independent class such as Matrix or Image has generally one provider and many users. The provider designs and usually implements the class. The users exercise the public interface made available by the provider. This separation of activity is reflected in the division of the class into a private implementation and a set of public methods and properties.

Under inheritance, there are multiple class providers: one providing the base-class implementation (and possibly some derived classes), and one or more providing derived classes throughout the lifetime of the inheritance hierarchy. This activity is also an implementation activity. The provider of the subtype often (but not always) needs access to portions of the base-class implementation. To allow such access, while still preventing general access to the implementation, we provide an additional access level, protected. The data members and member functions of a protected section of a class, although still unavailable to the general program, are available to the derived class.

The criteria for designating a member public to a class does not change between the design of a class that is intended to serve as a base class and one that is not. What does change is whether to declare a nonpublic member as protected or private. Any member specified as private within the base class is inaccessible to the derived classes.

A member is made protected if we believe it provides an operation or represents data necessary for the effective implementation of the derived class, but that we do not wish to make available to the general user of the class hierarchy. For example, the display_partial_solution() member of our Query base class provides a common service for each derived class, but it is not intended to be invoked directly by users of the Query class hierarchy. If we declare this method public, we cannot prevent its general use. While declaring it private prevents its general use, it also prevents a derived class from accessing it. The protected acess level provides us with the right level of access to accommodate both users of the class and implementers wishing to extend the class through inheritance.[2]

[2] There is some debate as to whether a derived class should directly access its base-class members or should access them through a base-class property. On the one hand, direct access results in a tight coupling between the base- and derived-class implementations—potentially inhibiting the evolution of the base class, or at least making that evolution more difficult. On the other hand, implementers of the derived class argue that direct member access is necessary to achieve acceptable performance.

What are the design considerations of a class that is intended to serve as a base class? We must identify the operations and properties that represent the public interface of the entire class hierarchy. We must then identify which of those operations are type dependent. These represent the virtual functions of our class hierarchy.

There is no magic formula for answering these questions or, once they have been answered, for guaranteeing either their correctness or their completeness. The process of object-oriented design is iterative and requires both additions to and modifications of our evolving class hierarchy. In the remainder of this chapter we walk through an iterative evolution of the Query class hierarchy.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.4.179