Previous Table of Contents Next


9.6.4. Creating and Initializing Objects

Classes, as noted, are a static notion. Objects appear at runtime; they are created explicitly.

The instruction that creates an object of type ACCOUNT and attaches it to x is written

   !! x

assuming that x has been declared of type ACCOUNT. Such an instruction must be in a routine of some class—the only place where instructions can appear—and its effect at runtime is threefold: Create a new object of type ACCOUNT, initialize its fields to default values, and attach the value of x to it. Here the object has two fields corresponding to the two attributes of the generating class: an integer for balance, which is initialized to 0, and a reference for all_deposits, which is initialized to a void reference (see Figure 9.6).


FIGURE 9.6.  An instance of ACCOUNT with fields initialized to defaults.

The default initialization values are specified for all possible types (see Figure 9.7).


FIGURE 9.7.  Types and corresponding default initialization values.

It is possible to override the initialization values by providing—as in the earlier example of class HELLO—one or more creation procedures. For example, we might change ACCOUNT to make sure that every account is created with an initial deposit:

   indexing
       description: “Simple bank accounts, initialized with a first
                    deposit”
   class
       ACCOUNT1
   creation
       make
   feature  -- Initialization
           make (sum: INTEGER) is
              -- Initialize account with sum.
           do
               deposit (sum)
           end
   ... The rest of the class as for ACCOUNT ...
   end  -- class ACCOUNT1

The newly added creation clause lists one or more (here just one) procedures of the class. In this case, the original form !! x is not valid any more for creating an instance of ACCOUNT1; a creation instruction must be of a form such as

   !! x.make (2000)

known as a creation call. Such a creation call has the same effect as the original form (creation, initialization, and attachment to x) followed by the effect of calling the selected creation procedure, which here calls deposit with the given argument.

Note that in this example all that make does is to call deposit. An alternative to introducing a new procedure make would have been simply to introduce a creation clause of the form creation deposit, elevating deposit to the status of creation procedure. Then a creation call would be of the form !! x.deposit (2000).

9.6.5. Entities

The example assumes x declared of type ACCOUNT (or ACCOUNT1). Such an x is an example of an entity, a notion generalizing the well-known concept of a variable. An entity is a name that appears in a class text to represent possible runtime values (a value being, as defined earlier, an object or a reference). An entity is one of the following:

  An attribute of the enclosing class, such as balance and all_deposits.
  A formal argument of a routine, such as sum for deposit and make.
  A local entity declared for the needs of a routine.
  The special entity Result in a function.

The third case, local entities, arises when a routine needs some auxiliary values for its computation. Here is an example of the syntax:

   deposit (sum: INTEGER) is
            -- Add sum to account.
       local
           new: AMOUNT
       do
           !! new.make (sum)
           all_deposits.extend (new)
           balance := balance + sum
       end

This example is a variant of deposit for which we assume that the elements of a DEPOSIT_LIST such as all_deposits are no longer just integers, but objects, instances of a new class, AMOUNT. Such an object contains an integer value and possibly other information as well. For the purpose of procedure deposit, we create an instance of AMOUNT and insert it, using procedure extend, into the list all_deposits. The object is identified through the local entity new, which is only needed within each execution of the routine (as opposed to an attribute, which yields an object field that remains in existence for as long as the object).

The last case of entity, Result, serves to denote, within the body of a function, the final result to be returned by that function. This was illustrated by the function deposits_count, which reads

   deposit_count: INTEGER is
        -- Number of deposits made since opening (provisional version)
       if all_deposits /= Void then
           Result := all_deposits.count
       end

The value returned by any call is the value of the expression all_deposits.count (to be explained in detail shortly) for that call, unless all_deposits has value Void, denoting a void reference (/= is not equal).

The default initialization rules seen earlier for attributes (Figure 9.7) also serve to initialize all local entities and Result on entry to a routine. In the last example, if all_deposits is void (as in the case on initialization with the class as given so far), Result keeps its default value of 0, which is returned as the result of the function.


Previous Table of Contents Next