This site's content was compiled from 1993 to 2006. Beyond that, Google is your friend.
Inheritance is one of the fundamental mechanisms for reuse—so is genericity. Genericity is also important in making programs type safe without resorting to type casts. Java does not have genericity, and many type casts are needed to make up for this deficiency—this is burdensome to the programmer. C++ has genericity in the form of template classes. If you have had problems understanding C++ templates—don’t worry—Eiffel’s generic syntax is much easier and more powerful because it also allows generic parameters to be constrained; this is known as constrained genericity (also known as bounded- and F-bounded polymorphism).
In order to use genericity you create a generic class with formal generic parameters. These are generic types where the type is left open to be instantiated by actual generic types. Generics are most useful in collection classes. For example, LISTs can store INTEGERs, ANIMALs, and other objects. Thus the LIST class is declared as:
class LIST [T] ... end
The actual lists are instantiated as:
il: LIST [INTEGER] -- LIST of INTEGERs animal_list: LIST [ANIMAL] -- LIST of ANIMALs list_list: LIST [LIST [INTEGER]] -- LIST of LISTs of INTEGERs
A generic class can also restrict the kinds of actual parameters. For example:
class SHELF [ITEM -> SHELF_ITEM] ... end
Here any actual generic type must be a SHELF_ITEM in order to instantiate a valid shelf.
The key point to remember about generics is that they allow you to write general algorithmic patterns that apply to a variety of types. The variety of types can be restricted with constrained genericity, where the genericity is known to work only on certain types. Where the generic types are not constrained, the algorithmic pattern is universally applicable.
Objects are created with the special create instruction. An example looks as follows:
c: C create c.make
or
create {D} c.make
In the first example, an object of type C is created and attached to the reference c. (Remember Eiffel is case insensitive, but the name c here is used for a variable and C for a class type, but there is no name clash.) In the second example, an object of type D, where D conforms to C (that is D is a subclass of C), is created and attached to c.
The other point to note is that, if you have a create routine declared for the
class, the create routine must be called. In the examples it is the make routine. In
order to flag a routine as a create routine, you must include it in the create clause at
the start of a class. (This clause used to be creation, but now the simple word create is used, so you don’t have to remember the difference between creation and
create.) Create routines are a bit like constructors in C++ and Java. More than one
can be declared, but unlike C++ and Java constructors, you can declare several create routines with the same signature.
class CAR inherit VEHICLE create make feature make is -- a create routine do ... end end -- CAR
Also different to C++ and Java is the fact that create routines can be called as normal routines. That is so long as the creation routines are exported as normal routines. The export status as a create routine and a normal routine can be different, so, if you really don’t want your create routines called as normal routines, you can prevent this.
Note that the !! creation syntax is still supported by Eiffel for CodeWarrior. You
will get a warning if the parser finds it in any .e file. You should not use the !! form
anymore—create does everything.
Eiffel has no delete instruction. This is because, as with Java, Eiffel is garbage collected. Garbage collection is known to completely cure the programming ills of dangling pointers and memory leaks. This greatly simplifies the programming effort by removing one of the largest bookkeeping headaches for programmers. Garbage collection has also proven to be very efficient in modern implementations.
In order to write routines, you use a sequence of instructions. As a point of terminology, Eiffel calls these instructions rather than statements, as in other languages. Eiffel provides the usual kinds of instructions: routine call, assignment, if then elseif ... else, loop, object creation and inspect (case or switch). These are just about the only instructions that Eiffel provides. Much of the power of Eiffel is provided in the libraries, which build upon the basic features of the language.
If you have used Smalltalk, C++, or Java, you will be wondering how to create class variables; that is variables which do not have one copy per object, but one per class of objects. The Eiffel equivalent for doing this is once routines. These are covered by the many other tutorials and books on Eiffel.