Previous Table of Contents Next


9.6.14. Execution Scenario

The preceding elements make it possible to understand the overall scheme of an Eiffel system’s execution.

At any time during the execution of a system, one object is the current object of the execution, and one of the routines of the system, the current routine, is executed with the current object as its target. (You will see later in this chapter how the current object and current routine are determined.) The text of a class, in particular its routines, make constant implicit references to the current object. For example, in the instruction

   balance := balance + sum

appearing in the body of procedure deposit of class ACCOUNT, the name of the attribute balance, in both occurrences, denotes the balance field of the current object, assumed to be an instance of ACCOUNT. In the same way, the procedure body that we have used for the creation procedure make in the ACCOUNT1 variant

   make (sum: INTEGER) is
        -- Initialize account with sum.
   do
       deposit (sum)
   end

contains a call to the procedure deposit. Contrary to earlier calls written in dot notation as target.feature (...), the call to deposit has no explicit target; this means its target is the current object, an instance of ACCOUNT1. Such a call is said to be unqualified; those using dot notations are qualified calls.

Although most uses of the current object are implicit, a class may need to name it explicitly. The predefined expression Current is available for that purpose. A typical use, in a routine merge (other: ACCOUNT) of class ACCOUNT, would be a test of the form

   if other = Current then
       report_error (“Error: trying to merge an account with    itself !”)
   else
       ... Normal processing (merging two different accounts) ...
   end

With these notions, it is not hard to define precisely the overall scenario of a system execution by defining what object and routine will be the current object and the current routine at each instant:

  Starting a system execution, as we have seen, consists in creating an instance of the root class, the root object, and executing a designated creation procedure, the root procedure, with the root object as its target. The root object is the initial current object, and the root procedure is the initial current procedure.
  From then on, only two events can change the current object and current procedure: a qualified routine call and the termination of a routine.
  In a call of the form target.routine (...), target denotes a certain object TC. (If target is an attribute, TC is the object attached to the corresponding field of the current object, which must be non-void for the call to proceed.) Then TC becomes the new current object. The generating class of TC must, according to the feature call rule, contain a routine of name routine, which becomes the new current routine.
  When a routine execution terminates, the target object and routine of the most recent non-terminated call (which just before the terminated call were the current object and the current routine) assume again the role of current object and current routine. This does not apply, of course, to the termination of the original root procedure call; in this case, the entire execution terminates and there is nothing more to say about it.

9.6.15. Abstraction

The description of assignments stated that in x := y, the target x must be an entity. More precisely, it must be a writable entity; this excludes formal routine arguments. As noted, a routine r (arg: SOME_TYPE) cannot assign to arg (reattaching it to a different object), although it can change the attached objects through calls of the form arg.procedure (...).

The restriction to an entity precludes in particular assignments of the form obj.some_attribute := some_value because the left-hand side, obj.some_attribute, is an expression (a feature call), not an entity, and you can no more assign to obj.some_attribute than to, say, a + b—another expression that is also, formally, a feature call.

To obtain the intended effect of the invalid assignment, you can use a procedure call of the form obj.set_attribute (some_value), where the base class of obj’s type has defined the procedure

   set_attribute (v: VALUE_TYPE) is
            -- Set value of attribute to v.
       do
           attribute := v
       end

This rule is essential to enforcing the method. Permitting direct assignments to an object’s fields would violate all the tenets of information hiding by circumventing the interface carefully crafted by the author of the supplier class. It is the responsibility of each class author to define the exact privileges that the class gives to each of its clients, in particular field modification rights. A field can be totally hidden (when the corresponding attribute is exported to NONE); it can be exported in read-only mode (when the attribute is exported, but no procedure modifies it); it can be exported in free-write mode (as with set_attribute if the class exports this procedure); it can also be exported in restricted-write mode, as with procedure deposit of class ACCOUNT, which allows addition of a certain amount to the balance field, but not direct setting of the balance. In such a case, the exported procedures may, thanks to the assertion mechanism reviewed later (section 9.8), place some further restrictions on the permitted modifications—for example, by requiring the withdrawn amount to be positive.


Previous Table of Contents Next