|
|
|
|
@@ -19,7 +19,7 @@ at the beginning of each affected routine; the first one to come in will perform
|
|
|
|
|
|
|
|
|
|
Once functions will give us shared objects. A common scheme is
|
|
|
|
|
<code>
|
|
|
|
|
console: WINDOW is
|
|
|
|
|
console: WINDOW
|
|
|
|
|
-- Shared console window
|
|
|
|
|
once
|
|
|
|
|
create Result.make (...)
|
|
|
|
|
@@ -38,16 +38,16 @@ The attributes studied earlier were variable: each represents a field present in
|
|
|
|
|
|
|
|
|
|
It is also possible to declare constant attributes, as in
|
|
|
|
|
<code>
|
|
|
|
|
Solar_system_planet_count: INTEGER is 9
|
|
|
|
|
Solar_system_planet_count: INTEGER = 9
|
|
|
|
|
</code>
|
|
|
|
|
|
|
|
|
|
These will have the same value for every instance and hence do not need to occupy any space in objects at execution time. (In other approaches similar needs would be addressed by symbolic constants, as in Pascal or Ada, or macros, as in C.)
|
|
|
|
|
|
|
|
|
|
What comes after the <code>is</code> is a manifest constant: a self-denoting value of the appropriate type. Manifest constants are available for integers, reals (also used for doubles), booleans ( <code>True</code> and <code>False</code>), characters (in single quotes, as <code>'A'</code>, with special characters expressed using a percent sign as in <code>'%N'</code> for new line, <code>'%B'</code> for backspace and <code>'%U'</code> for null).
|
|
|
|
|
What comes after the <code>=</code> is a manifest constant: a self-denoting value of the appropriate type. Manifest constants are available for integers, reals (also used for doubles), booleans ( <code>True</code> and <code>False</code>), characters (in single quotes, as <code>'A'</code>, with special characters expressed using a percent sign as in <code>'%N'</code> for new line, <code>'%B'</code> for backspace and <code>'%U'</code> for null).
|
|
|
|
|
|
|
|
|
|
For integer constants, it is also possible to avoid specifying the values. A declaration of the form
|
|
|
|
|
<code>
|
|
|
|
|
a, b, c, ... n : INTEGER is unique
|
|
|
|
|
a, b, c, ... n : INTEGER = unique
|
|
|
|
|
</code>
|
|
|
|
|
|
|
|
|
|
introduces <code>a</code>, <code>b</code>, <code>c</code>, ... <code>n</code> as constant integer attributes, whose value are assigned by the Eiffel compiler rather than explicitly by the programmer. The values are different for all <code>unique</code> attributes in a system; they are all positive, and, in a single declaration such as the above, guaranteed to be consecutive (so that you may use an invariant property of the form <code>code > a and code < n</code> to express that <code>code</code> should be one of the values). This mechanism replaces the "enumerated types" found in many languages, without suffering from the same problems. (Enumerated types have an ill-defined place in the type system; and it is not clear what operations are permitted.)
|
|
|
|
|
@@ -70,7 +70,17 @@ which is an expression of type <code>ARRAY [INTEGER]</code>. Manifest arrays and
|
|
|
|
|
|
|
|
|
|
Eiffel has a remarkably small set of instructions. The basic computational instructions have been seen: creation, assignment, assignment attempt, procedure call, retry. They are complemented by control structures: conditional, multi-branch, loop, as well as debug and check.
|
|
|
|
|
|
|
|
|
|
A conditional instruction has the form <code>if</code> ... <code>then</code> ... <code>elseif</code> ... <code>then</code> ... <code>else</code> ... <code>end</code>. The <code>elseif</code> ... <code>then</code> ... part (of which there may be more than one) and the <code>else</code> ... part are optional. After <code>if</code> and <code>elseif</code> comes a boolean expression; after <code>then</code>, <code>elseif</code> and <code>else</code> come zero or more instructions.
|
|
|
|
|
A conditional instruction has the form
|
|
|
|
|
<code>
|
|
|
|
|
if ... then
|
|
|
|
|
...
|
|
|
|
|
elseif ... then
|
|
|
|
|
...
|
|
|
|
|
else
|
|
|
|
|
...
|
|
|
|
|
end
|
|
|
|
|
</code>
|
|
|
|
|
The <code>elseif</code> ... <code>then</code> ... part (of which there may be more than one) and the <code>else</code> ... part are optional. After <code>if</code> and <code>elseif</code> comes a boolean expression; after <code>then</code>, <code>elseif</code> and <code>else</code> come zero or more instructions.
|
|
|
|
|
|
|
|
|
|
A multi-branch instruction has the form
|
|
|
|
|
<code>
|
|
|
|
|
@@ -86,7 +96,7 @@ else
|
|
|
|
|
end
|
|
|
|
|
</code>
|
|
|
|
|
|
|
|
|
|
where the <code>else</code> ''inst0'' part is optional, <code>exp</code> is a character or integer expression, ''v1'', ''v1'', ... are constant values of the same type as <code>exp</code>, all different, and ''inst0'', ''inst1'', ''inst2'', ... are sequences of zero or more instructions. In the integer case, it is often convenient to use <code>unique</code> values ( [[10 Other Mechanisms|"Constant and unique attributes", page 83]] ) for the ''vi''
|
|
|
|
|
where the <code>else ''inst0''</code> part is optional, <code>exp</code> is a character or integer expression, ''v1'', ''v1'', ... are constant values of the same type as <code>exp</code>, all different, and ''inst0'', ''inst1'', ''inst2'', ... are sequences of zero or more instructions. In the integer case, it is often convenient to use <code>unique</code> values ( [[10 Other Mechanisms|"Constant and unique attributes", page 83]] ) for the ''vi''.
|
|
|
|
|
|
|
|
|
|
The effect of such a multi-branch instruction, if the value of <code>exp</code> is one of the ''vi'', is to execute the corresponding ''insti''. If none of the ''vi'' matches, the instruction executes ''inst0'', unless there is no <code>else</code> part, in which case it triggers an exception.
|
|
|
|
|
|
|
|
|
|
@@ -115,11 +125,16 @@ The assertion ''inv'', if present, expresses a '''loop invariant''' (not to be c
|
|
|
|
|
|
|
|
|
|
An occasionally useful instruction is <code>debug</code> <code>(</code>''Debug_key'', ... <code>)</code> ''instructions'' <code>end</code> where ''instructions'' is a sequence of zero or more instructions and the part in parentheses is optional, containing if present one or more strings, called debug keys. The EiffelStudio compiler lets you specify the corresponding <code>debug</code> compilation option: <code>yes</code>, <code>no</code>, or an explicit debug key. The ''instructions'' will be executed if and only if the corresponding option is on. The obvious use is for instructions that should be part of the system but executed only in some circumstances, for example to provide extra debugging information.
|
|
|
|
|
|
|
|
|
|
The final instruction is connected with Design by Contract™. The instruction <code>check</code> ''Assertion'' <code>end</code>, where ''Assertion'' is a sequence of zero or more assertions, will have no effect unless assertion monitoring is turned on at the <code>Check</code> level or higher. If so it will evaluate all the assertions listed, having no further effect if they are all satisfied; if any one of them does not hold, the instruction will trigger an exception.
|
|
|
|
|
The final instruction is connected with Design by Contract™. The instruction
|
|
|
|
|
<code>
|
|
|
|
|
check
|
|
|
|
|
Assertion
|
|
|
|
|
end
|
|
|
|
|
</code>, where Assertion is a sequence of zero or more assertions, will have no effect unless assertion monitoring is turned on at the <code>Check</code> level or higher. If so it will evaluate all the assertions listed, having no further effect if they are all satisfied; if any one of them does not hold, the instruction will trigger an exception.
|
|
|
|
|
|
|
|
|
|
This instruction serves to state properties that are expected to be satisfied at some stages of the computation -- other than the specific stages, such as routine entry and exit, already covered by the other assertion mechanisms such as preconditions, postconditions and invariants. A recommended use of <code>check</code> involves calling a routine with a precondition, where the call, for good reason, does not explicitly test for the precondition. Consider a routine of the form
|
|
|
|
|
<code>
|
|
|
|
|
r (ref: SOME_REFERENCE_TYPE) is
|
|
|
|
|
r (ref: SOME_REFERENCE_TYPE)
|
|
|
|
|
require
|
|
|
|
|
not_void: ref /= Void
|
|
|
|
|
do
|
|
|
|
|
@@ -130,7 +145,9 @@ r (ref: SOME_REFERENCE_TYPE) is
|
|
|
|
|
|
|
|
|
|
Because of the call to <code>some_feature</code>, the routine will only work if its precondition is satisfied on entry. To guarantee this precondition, the caller may protect it by the corresponding test, as in
|
|
|
|
|
<code>
|
|
|
|
|
if x /= Void then a.r (x) end
|
|
|
|
|
if x /= Void then
|
|
|
|
|
a.r (x)
|
|
|
|
|
end
|
|
|
|
|
</code>
|
|
|
|
|
|
|
|
|
|
but this is not the only possible scheme; for example if an <code>create x</code> appears shortly before the call we know <code>x</code> is not void and do not need the protection. It is a good idea in such cases to use a <code>check</code> instruction to document this property, if only to make sure that a reader of the code will realize that the omission of an explicit test (justified or not) was not a mistake. This is particularly appropriate if the justification for not testing the precondition is less obvious. For example <code>x</code> could have been obtained, somewhere else in the algorithm, as <code>clone (y)</code> for some <code>y</code> that you know is not void. You should document this knowledge by writing the call as
|
|
|
|
|
@@ -155,7 +172,7 @@ This raises the issue of backward compatibility: how to move forward with a bett
|
|
|
|
|
|
|
|
|
|
The notion of obsolete class and feature helps address this issue. By declaring a feature as <code>obsolete</code>, using the syntax
|
|
|
|
|
<code>
|
|
|
|
|
enter (i: INTEGER; x: G) is
|
|
|
|
|
enter (i: INTEGER; x: G)
|
|
|
|
|
obsolete
|
|
|
|
|
"Use ` put (x, i)' instead "
|
|
|
|
|
require
|
|
|
|
|
@@ -253,8 +270,7 @@ Features available on tuple types include <code>count: INTEGER</code>, yielding
|
|
|
|
|
|
|
|
|
|
Tuples are appropriate when these are the only operations you need, that is to say, you are using sequences with no further structure or properties. Tuples give you "anonymous classes" with predefined features <code>count</code>, <code>item</code> and <code>put</code>. A typical example is a general-purpose output procedure that takes an arbitrary sequence of values, of arbitrary types, and prints them. It may simply take an argument of type <code>TUPLE</code>, so that clients can call it under the form
|
|
|
|
|
<code>
|
|
|
|
|
|
|
|
|
|
write ([ ''your_integer'' , ''your_real'', ''your_account''])
|
|
|
|
|
write ([your_integer, your_real, your_account])
|
|
|
|
|
</code>
|
|
|
|
|
|
|
|
|
|
As soon as you need a type with more specific features, you should define a class.
|
|
|
|
|
|