Previous | Table of Contents | Next |
The notion of class is central to the Eiffel approach. A class is the description of a type of runtime data structures (objects), characterized by common operations (features) and properties. Examples of classes include
We may characterize the first of these examples as an analysis class, directly modeling objects from the application domain; the second one as a design class, describing a high-level solution; and the third as an implementation class, reused whenever possible from a library such as EiffelBase. In Eiffel, however, there is no strict distinction between these categories; it is part of the approachs seamlessness that the same notion of class, and the associated concepts, may be used at all levels of the software development process.
Two relations can exist between classes:
If C is a client of A, A is a supplier of C. If B is an heir of A, A is a parent of B. A descendant of A is either A itself or, recursively, a descendant of an heir of A; in more informal terms, a descendant is a direct or indirect heir, or the class itself. To exclude A itself, we talk of proper descendant. In the reverse direction, the terms are ancestor and proper ancestor.
The client relation can be cyclic; an example involving a cycle would be classes PERSON and HOUSE, modeling the corresponding informal everyday object types and expressing the properties that every person has a home and every home has an architect. The inheritance (heir) relation may not include any cycle.
In modeling terms, client roughly represents the relation has, and heir roughly represents is. For example, we may use Eiffel classes to model a certain system and express that every child has a birth date (client relation) and is a person (inheritance).
Distinctive of Eiffel is the rule that classes can only be connected through these two relations. This excludes the behind-the-scenes dependencies often found in other approaches, such as the use of global variables, which jeopardize the modularity of a system. Only through a strict policy of limited and explicit interclass relations can we achieve the goals of reusability and extendibility.
If you write an Eiffel class, it does not come into a vacuum but fits in a preordained structure, shown in Figure 9.3 and involving a few library classes: GENERAL, ANY, and NONE.
FIGURE 9.3. The global inheritance structure.
Any class that does not explicitly inherit from another is considered to inherit from ANY, which itself inherits from GENERAL. This makes GENERAL an ancestor of all developer-written classes (with an exception explained later). GENERAL introduces a number of general-purpose features useful everywhere; examples include copying, cloning, and equality testing operations (section 9.6.10), and default input/output mechanisms.
ANY, as delivered, is empty except for the clause stating that it inherits from GENERAL. Individual companies, groups, or projects can add features to it to provide general mechanisms available to all classes developed in a certain environment. This also gives the ability (not frequently useful) to produce classes that are not descendants of GENERAL: Just redefine ANY so that it ceases to be an heir of GENERAL.
NONE is a fictitious class, which is considered to be an heir of any class that has no explicit heir. Because inheritance has no cycles, NONE cannot have proper descendants. This makes it useful, as you will see, to specify non-exported features and to denote the type of void values.
Classes are the only form of module in Eiffel. As is explained in more detail later, they also provide the basis for the only form of type. This module-type identification is at the heart of object technology and yields the fundamental simplicity of the Eiffel method.
Efforts to introduce a higher-level notion of module above classes are misguided because they introduce a whole new set of issues (namespace, name visibility, information hiding, separate compilation, and module inclusion) to which the solutions would clash with the class-level techniques. This would also hamper reusability (by making it harder to reuse a class by itself) and extendibility.
There is a need, however, for an organizational concept: cluster. A cluster is a group of related classes. The cluster is a property of the method, enabling managers to organize the development into teams, but it does not require a specific Eiffel language construct. As we have already seen (section 9.3.1), it also plays a central role in the lifecycle model.
Previous | Table of Contents | Next |