Previous Table of Contents Next


9.6.2. Features

A feature, as noted, is an operation available on instances of a class. A feature can be either an attribute or a routine. This classification, which can be followed by starting from the right on Figure 9.5, is based on implementation considerations.


FIGURE 9.5  Feature categories (two complementary classifications).

  An attribute is a feature implemented through memory: It describes a field that is found in all instances of the class. For example, class ACCOUNT may have an attribute balance; then all instances of the class have a corresponding field containing each account’s current balance.
  A routine describes a computation applicable to all instances of the class. ACCOUNT may have a routine withdraw.

Routines are further classified into functions, which return results, and procedures, which do not. Routine withdraw is a procedure; an example of a function may be highest_deposit, which returns the highest deposit made so far to the account.

From the viewpoint of classes relying on a certain class (its clients), the more relevant classification is the one coming from the left on Figure 9.5:

  Commands have no result and can modify an object. They can only be procedures.
  Queries have a result: They return information about an object. They can be implemented as either attributes (by reserving space for the corresponding information in each instance of the class, a memory-based solution) or functions (a computation-based solution). An attribute is only possible for a query without argument, such as balance; a query with arguments, such as balance_on (d), returning the balance at date d, can only be a function.

From the outside, there is no difference between a query implemented as an attribute and one implemented as a function: To obtain the balance of an account a, you always write a.balance.

In the implementation suggested previously, a is an attribute so that the notation denotes an access to the corresponding object field. It is also possible to implement a as a function, whose algorithm explores the lists of deposits and withdrawals and computes their accumulated value. To the clients of the class, and in the official class documentation as produced by the environment tools, the difference is not visible.

This principle of uniform access supports Eiffel’s goals of extendibility, reusability, and maintainability: You can change the implementation without affecting clients, and you can reuse a class without having to know the details of its features’ implementations.

9.6.3. A Simple Class

The following simple class text illustrates the preceding concepts:

   indexing
       description: “Simple bank accounts”
   class
       ACCOUNT
   feature  -- Access
       balance: INTEGER
                -- Current balance
       deposit_count: INTEGER is
                -- Number of deposits made since opening
           do
               if all_deposits /= Void then
                   Result := all_deposits.count
               end
           end
   feature  -- Element change
       deposit (sum: INTEGER) is
                -- Add sum to account.
           do
               if all_deposits= Void then
                   !! all_deposits
               end
               all_deposits.extend (sum)
               balance := balance + sum
           end
   feature {NONE}  -- Implementation
       all_deposits: DEPOSIT_LIST
                -- List of deposits since account’s opening.
   invariant
       consistent_balance: (all_deposits /= Void)
           implies (balance = all_deposits.total)
       zero_if_no_deposits: (all_deposits = Void)
           implies (balance = 0)
   end  -- class ACCOUNT

(The {NONE} qualifier and the invariant clause, used here to make the example closer to a real class, are explained shortly. DEPOSIT_LIST refers to another class, which can be written separately using library classes.)

The category to which each feature belongs is easy to deduce from its syntactic appearance. Here only deposit and deposit_count, which include a do... clause, are routines; balance and all_deposits, which are simply declared with a type, are attributes. Note that even for attributes it is recommended to have a header comment.

Routine deposit_count is declared as returning a result (of type INTEGER), so it is a function. Routine deposit has no such result and hence is a procedure.


Previous Table of Contents Next