- Invitation to Eiffel (I2E)
- I2E: What Must I Know First?
- I2E: Design Principles
- I2E: Object-Oriented Design
- I2E: Classes
- I2E: Types
- I2E: Design by Contract and Assertions
- I2E: Exceptions
- I2E: Event-Driven Programming and Agents
- I2E: Genericity
- I2E: Inheritance
- I2E: Polymorphism and Dynamic Binding
- I2E: Combining Genericity and Inheritance
- I2E: Deferred Classes and Seamless Development
- I2E: Putting a System Together
- I2E: Invitation to Eiffel Copyright
- An Eiffel Tutorial (ET)
- Void-safe programming in Eiffel
- Quick reference to the Eiffel programming language
- Books about the Eiffel Method and Language
- Method and Language beta documentation
Inheritance, the other fundamental generalization mechanism, makes it possible to define a new class by combination and specialization of existing classes rather than from scratch.
The following simple example, from the Data Structure Library in EiffelBase, is typical.
LIST, as noted, describes lists in any representation. One such representation if the lists have a fixed number of elements uses an array. We may define the corresponding class by combination of
ARRAY, as follows:
inherit ... clause lists all the "parents" of the new class, which is said to be their "heir". (The "ancestors" of a class include the class itself, its parents, grandparents etc.; the reverse term is "descendant".) Declaring
ARRAYED_LIST as shown ensures that all the features and properties of lists and arrays are applicable to arrayed lists as well. Since the class has more than one parent, this is a case of multiple inheritance.
Standard graphical conventions -- drawn from the Business Object Notation or BON, a graphical object-oriented notation based on concepts close to those of Eiffel, and directly supported by EiffelStudio -- illustrate such inheritance structures:
An heir class such as
ARRAYED_LIST needs the ability to define its own export policy. By default, inherited features keep their export status (publicly available, secret, available to selected classes only); but this may be changed in the heir. Here, for example,
ARRAYED_LIST will export only the exported features of
LIST, making those of
ARRAY unavailable directly to
ARRAYED_LIST 's clients. The syntax to achieve this is straightforward:
Another example of multiple inheritance comes from a windowing system based on a class
WINDOW, close to actual classes in EiffelVision 2. Windows have graphical features: a height, a width, a position, routines to scale windows, move them, and other graphical operations. The system permits windows to be nested, so that a window also has hierarchical features: access to sub windows and the parent window, adding a sub window, deleting a sub window, attaching to another parent and so on. Rather than writing complex class that would contain specific implementations for all of these features, it is preferable to inherit all hierarchical features from
TREE (a class in EiffelBase describing trees), and all graphical features from a class
Inheritance complements the "client" relation by providing another form of reuse that yields remarkable economies of effort -- for analysis, design, implementation, evolution -- and has a profound effect on the entire software development process.
The very power of inheritance demands adequate means to keep it under control. Multiple inheritance, in particular, raises the question of name conflicts between features inherited from different parents; this case will inevitably arise in practice, especially for classes contributed by independent developers. You may remove such a name conflict through renaming, as in
class C inherit A rename x as x1, y as y1 end B rename x as x2, y as y2 end feature ...
Here, if both
B have features named
C would be invalid without the renaming.
Renaming also serves to provide more appropriate feature names in descendants. For example, class
WINDOW may inherit a routine
TREE. For clients of
WINDOW, however, such a routine name is no longer appropriate. An application that uses this class needs coherent window terminology, and should have to concern itself with the inheritance structure that led to the class. So you may wish to rename
add_subwindow in the inheritance clause of
As a further protection against misusing multiple inheritance, the invariants of all parent classes automatically apply to a newly defined class. So classes may not be combined if their invariants are incompatible.