Previous Table of Contents Next


9.6.6. Calls

Apart from object creation, the basic computational mechanism, in the object-oriented style of computation represented by Eiffel, is the feature call. In its basic form, it appears as

   target.feature (argument1, ...)

where target is an entity (it can more generally be an expression), feature is a feature name, and there may be zero or more argument expressions. In the absence of any argument, the part in parentheses should be removed.

We have already seen such calls. If feature denotes a procedure, the call is an instruction, as in

   all_deposits.extend (new)

If feature denotes a query (function or attribute), the call is an expression, as in the right-hand side of

   Result := all_deposits.count

The principle of uniform access (section 9.6.2) implies that this form is the same for an attribute and for a function without arguments. (The feature used in this example, count from class DEPOSIT_LIST, could indeed be implemented in either of these two ways: We can keep a count field in each list, updating it for each insertion and removal, or we can compute count, whenever requested, by traversing the list to count the number of elements.)

In the case of a routine with arguments—procedure or function—the routine is declared, in its class, as

   feature ( formal1: TYPE1; ...) is
       do ... end

meaning that, at the time of each call, the value of each formal is set to the corresponding actual (formal1 to argument1 and so on). In the routine body, it is not permitted to change the value of a formal argument, although it is possible to change the value of an attached object through a procedure call such as formal1.some_procedure (...).

9.6.7. Infix and Prefix Notation

Basic types such as INTEGER are, as noted, part of Eiffel’s uniform type system, so they are declared as classes (part of the kernel library). INTEGER, for example, is characterized by the features describing integer operations: plus, minus, times, division, less than, and so on.

With the dot notation seen so far, this would imply that simple arithmetic operations would have to be written with a syntax such as i.plus (j) instead of the usual i + j. This is awkward. Infix and prefix features solve the problem, reconciling the object-oriented view of computation with common notational practices of mathematics. The addition function is declared in class INTEGER as

   infix “+” (other: INTEGER): INTEGER is
       do ... end

Such a feature has all the properties and prerogatives of a normal identifier feature, except for the form of the calls, which is infix, as in i + j, rather than dot notation. An infix feature must be a function and take exactly one argument. Similarly, a function can be declared as prefix “ --”, with no argument, permitting calls of the form --3 rather than (3).negated.

Predefined library classes covering basic types such as INTEGER, CHARACTER, BOOLEAN, REAL, and DOUBLE are known to the Eiffel compiler so that a call of the form i + j, although conceptually equivalent to a routine call, can be processed just as efficiently as the corresponding arithmetic expression in an ordinary programming language. This brings the best of both worlds: conceptual simplicity, enabling Eiffel developers, when they want to, to think of integers and the like as objects and efficiency as good as in lower-level approaches.

Infix and prefix features can be used in any class, not just predefined classes for basic types. For example, a graphics class could use the name infix| --| for a function computing the distance between two points, to be used in expressions such as point1 | --| point2.

9.6.8. Type Declaration

Every entity in Eiffel is declared as a certain type, using the syntax already encountered in the preceding examples:

   entity_name: TYPE_NAME

This applies to attributes, formal arguments of routines, and local entities. The result type is also declared for a function, as in the earlier example

   deposit_count: INTEGER is ...

Here the type also serves as the type implicitly declared for Result in the function’s body.

What is a type? With the elements seen so far, every type is a class. INTEGER, used in the declaration of deposits_count, is, as we have seen, a library class, and the declaration all_deposits: DEPOSIT_LIST assumes the existence of a class DEPOSIT_LIST.

Three mechanisms introduced later in this chapter—expanded types (section 9.6.9), genericity (section 9.7) and anchored declarations (section 9.9.16)—generalize the notion of type slightly. But they do not change the fundamental property that every type is based on a class, called the type’s base class. In the examples seen so far, each type is a class, serving as its own base class. An instance of a class C is also called an object of type C.


Previous Table of Contents Next