Author:halw

Date:2008-10-16T21:05:31.000000Z


git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@84 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
halw
2008-10-16 21:31:11 +00:00
parent 3e5e123581
commit dd18a6e406

View File

@@ -6,7 +6,7 @@ A system with a certain static structure describes a set of possible executions.
The properties of the run-time model are not just of interest to implementers; they also involve concepts directly relevant to the needs of system modelers and analysts at the most abstract levels.
==Objects, fields, values and references==
==Objects, fields, values, and references==
A class was defined as the static description of a type of run-time data structures. The data structures described by a ca class are called '''instances''' of the class, which in turn is called their '''generating class''' (or just "generator"). An instance of <code> ACCOUNT </code> is a data structure representing a bank account; an instance of <code> LINKED_LIST </code> is a data structure representing a linked list.
@@ -203,7 +203,7 @@ known as a creation call. Such a creation call will have the same effect as the
Note that in this example all that <code> make </code> does is to call <code> deposit </code>. So an alternative to introducing a new procedure <code> make </code> would have been simply to introduce a creation clause of the form <code> create </code> <code> deposit </code>, elevating <code> deposit </code> to the status of creation procedure. Then a creation call would be of the form <code> create x.deposit (2000)</code> .
{{info|Some variants of the basic creation instruction will be reviewed later: instruction with an explicit type; creation expressions. See [[10 Other Mechanisms|"Creation variants", page 89]] . }}
{{info|Some variants of the basic creation instruction will be reviewed later: instruction with an explicit type; creation expressions. See [[10 Other Mechanisms#Creation_variants|"Creation variants"]] . }}
==Entities==
@@ -235,14 +235,14 @@ deposit_count: INTEGER
-- Number of deposits made since opening (provisional version)
do
if all_deposits /= Void then
Result := all_deposit.count
Result := all_deposits.count
end
end
</code>
The value returned by any call will be the value of the expression <code> all_deposits </code>. <code> count </code>(to be explained in detail shortly) for that call, unless <code> all_deposits </code> has value <code> ensure </code>, denoting a void reference ( <code>/</code> is "not equal").
The value returned by any call will be the value of the expression <code>all_deposits.count</code> (to be explained in detail shortly) for that call, unless <code>all_deposits /code> is a <code>Void</code> reference ( <code>/=</code> means "not equal").
The default initialization rules seen earlier for attributes (see the table on page [[6 The Dynamic Structure: Execution Model|21]] ) also serve to initialize local entities and <code> Result </code> on routine entry. So in the last example, if <code> all_deposits </code> is void (as in the case on initialization with the class as given so far), <code> Result </code> keeps its default value of 0, which will be returned as the result of the function.
The default initialization rules seen earlier for attributes (see the table above) also serve to initialize local entities and <code>Result</code> on routine entry. So in the last example, if <code>all_deposits</code> is void (as in the case on initialization with the class as given so far), <code>Result</code> keeps its default value of 0, which will be returned as the result of the function.
==Calls==
@@ -263,7 +263,7 @@ If <code> feature </code> denotes a query (function or attribute), the call is a
Result := all_deposits.count
</code>
Following the principle of Uniform Access (page [[6 The Dynamic Structure: Execution Model|19]] ), this form is the same for calls to attributes and to functions without arguments. In this example, feature <code> count </code> from class <code> DEPOSIT_LIST </code> may indeed be implemented in either of these two ways: we can keep a <code> count </code> field in each list, updating it for each insertion and removal; or we can compute <code> count </code>, whenever requested, by traversing the list and counting the number of items.
Following the principle of Uniform Access (mentioned earlier in the section ''Objects, fields, values, and references''), this form is the same for calls to attributes and to functions without arguments. In this example, feature <code>count</code> from class <code>DEPOSIT_LIST</code> may indeed be implemented in either of these two ways: we can keep a <code>count /code> field in each list, updating it for each insertion and removal; or we can compute <code>count</code>, whenever requested, by traversing the list and counting the number of items.
In the case of a routine with arguments -- procedure or function -- the routine will be declared, in its class, as
<code>
@@ -311,7 +311,7 @@ Specifying such a function result type also declares, implicitly, the type for <
What is a type? With the elements seen so far, every type is a <code>class</code> . <code>INTEGER</code>, used in the declaration of <code>deposits_count</code>, is, as we have seen, a library class; and the declaration <code> all_deposits </code>: <code> DEPOSIT_LIST </code> assumes the existence of a class <code> DEPOSIT_LIST </code>.
Three mechanisms introduced below -- expanded types (page [[6 The Dynamic Structure: Execution Model|26]] ), genericity (page [[7 Genericity and Arrays|36]] ) and anchored declarations (page [[9 Inheritance|79]] ) -- will 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.
Three mechanisms introduced below -- expanded types, genericity, and anchored declarations -- will 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 <code>C</code> is also called "an object of type <code>C</code>".
@@ -355,7 +355,7 @@ In this case the value of an entity declared as <code> n:INTEGER</code> is not a
It is also possible, for some non-expanded class C, to declare an entity as
<code>
x: expanded
x: expanded C
</code>
so that the values for <code>x</code> will be objects of type <code>C</code>, rather than references to such objects. This is our first example of a type -- <code>expanded C</code> -- that is not directly a class, although it is based on a class, <code>C</code>. The base type of such a type is <code>C</code>.
@@ -408,23 +408,33 @@ For entities of expanded types, the values are objects; the object attached to <
To copy an object, use <code>x.copy (y)</code> which assumes that both <code>x</code> and <code>y</code> are non-void, and copies the contents of <code>y</code>'s attached object onto those of <code>x</code>'s. For expanded entities the effect is the same as that the of the assignment <code>x := y</code>.
A variant of the <code>copy</code> operation is <code> twin</code> . The expression <code> y.twin</code> produces a newly created object, initialized with a copy of the object attached to <code> y </code>, or a void value if <code> y </code> itself is void. For a reference type (the only interesting case) the returned result for non-void is <code> y</code> a reference to the new object. This means we may view <code> twin</code> as a function that performs
An operation performing similar duty to the <code>copy</code> is <code> twin</code> . The assignment
<code>
x := y.twin
</code>
produces a newly created object (provided that <code>y</code> is non-void), initialized with a copy of the object attached to <code>y</code> and attaches the result to <code>x</code> . This means we may view <code> twin</code> as a function that performs the following two steps:
<code>
create Result
Result.copy (y)
Result.copy (Current)
</code>
The new object is created, then its content is updated to match the content of <code>y</code> to which the <code>twin</code> call is targeted.
So in the assignment <code> x := y.twin</code> , assuming both entities of reference types and <code> y </code> not void, will attach <code> x </code> to a '''new object''' identical to <code> y </code> 's attached object, as opposed to the assignment <code> x := y </code> which attaches <code> x </code> to the '''same object''' as <code> y </code>.
So, assuming both entities of reference types and <code>y</code> not void, the assignment above will attach <code>x</code> to a '''new object''' identical to <code>y</code>'s attached object, as opposed to the assignment <code> x := y </code> which attaches <code>x</code> to the '''same object''' as <code>y</code>.
To determine whether two values are equal, use the expression <code> x := y </code>. For references, this comparison will yield true if the values are either both void or both attached to the same object; this is the case in the last figure in the state after the assignment, but not before. The symbol for not equal is <code> /= </code>, as in <code> x /= y </code>.
As with assignment, there is also a form that works on objects rather than references: <code> x </code>. <code> is_equal </code> ( <code> y </code>) will return true when <code> x </code> and <code> y </code> are both non-void and attached to field-by-field identical objects. This can be true even when <code> x </code> <code> y </code> is not, for example, in the figure, <code> before </code> the assignment, if the two objects shown are field-by-field equal.
To determine whether two values are equal, use the expression <code> x = y </code>. For references, this comparison will yield true if the values are either both void or both attached to the same object; this is the case in the last figure in the state after the assignment, but not before. The symbol for not equal is <code> /= </code>, as in <code> x /= y </code>.
A more general variant of <code> is_equal </code> is used under the form <code> equal </code> ( <code> x </code>, <code> y </code>). This is always defined, even if <code> x </code> is void, returning true whenever <code> is_equal </code> would but also if <code> x </code> and <code> y </code> are both void. (In contrast, <code> x </code>. <code> is_equal </code> ( <code> y </code>) is not defined for void <code> x </code> and would, if evaluated, yield an exception as explained in [[8 Design by Contract (tm), Assertions and Exceptions|"Exception handling", page 46]] below.)
As with assignment, there is also a form that works on objects rather than references: <code>x.is_equal (y)</code> will return true when <code>x</code> and <code>y</code> are both non-void and attached to field-by-field identical objects. This can be true even when <code>x = y</code> is not, for example, in the figure, before the assignment, if the two objects shown are field-by-field equal.
<code>Void</code> denotes a void reference. So you can make <code> x </code> void through the assignment <code> x := Void </code>, and test whether it is void through <code> if </code> <code> x = Void </code> <code> then </code> ...
A more general variant of <code>is_equal</code> is used under the form <code>equal (x, y)</code> . This is always defined, even if <code>x</code> is void, returning true whenever <code>is_equal</code> would but also if <code>x</code> and <code>y</code> are both void. (In contrast, <code>x.is_equal (y)</code> is not defined for void <code>x</code> and would, if evaluated, yield an exception as explained in [[8 Design by Contract (tm), Assertions and Exceptions#Exception_handling|"Exception handling"]] below.)
Where assignment <code> := </code> and the equality operators <code> = </code> and <code> /= </code> were language constructions, <code> copy </code>, <code> twin</code>, <code> is_equal </code>, <code> equal </code> and <code> ensure </code> are '''library features''' coming from class <code> ANY </code>. The type of <code> ensure </code>, as declared in <code> ANY </code>, is <code> NONE </code>, the "bottom" type.
<code>Void</code> denotes a void reference. So you can make <code>x</code> void through the assignment <code>x := Void</code>, and test whether it is void through:
<code>
if x = Void then ...</code>
Where assignment, <code>:=</code> , and the equality operators, <code>=</code> and <code>/=</code> , were language constructions, <code>copy</code>, <code>twin</code>, <code>is_equal</code>, and <code>equal</code> are '''library features''' coming from class <code> ANY </code>.
<code>Void</code> is a language keyword with built-in functionality, but it is not far out of bounds to think of <code>Void</code> as another feature declared in <code> ANY </code>, but with type of <code>NONE</code>, the "bottom" type.
Using the redefinition mechanisms to be seen in the discussion of inheritance, a class can redefine <code>copy</code> and <code>is_equal</code> to cover specific notions of copy and equality. The assertions will ensure that the two remain compatible: after <code>x.copy (y)</code> , the property <code>x .is_equal (y)</code> must always be true. The effect of <code>twin</code> will automatically follow a redefinition of <code>copy</code>, and <code>equal</code> will follow <code>is_equal</code>.
@@ -447,10 +457,7 @@ As the name suggests, <code> Some_file_or_network_connection </code> can be an e
==Memory management==
Reference reattachments
<code>
x := y </code>
of the form illustrated by the figure just above can cause objects to become unreachable. This is the case for the object identified as OBJ1 on that figure (the object to which <code> x </code> was attached before the assignment) if no other reference was attached to it.
Reference reattachments, <code>x := y</code> , of the form illustrated by the figure just above can cause objects to become unreachable. This is the case for the object identified as OBJ1 on that figure (the object to which <code>x</code> was attached before the assignment) if no other reference was attached to it.
In all but toy systems, it is essential to reclaim the memory that has been allocated for such objects; otherwise memory usage could grow forever, as a result of creation instructions <code>create x</code> ... and calls to <code>twin</code> and the like, leading to thrashing and eventually to catastrophic termination.
@@ -466,8 +473,7 @@ The Eiffel Software's implementation of Eiffel provides a sophisticated '''garba
The basic form of computation, it has been noted, is a call of the form <code>target.feature (...)</code> . This is only meaningful if <code>feature</code> denotes a feature of the generating class of the object to which <code>target</code> (assumed to be non-void) is attached. The precise rule is the following:
{{note|Feature Call rule A call of the form <code>target.feature (...)</code> appearing in a class C is only valid if feature is a feature of the base class of target 's type, and is available to C.}}
{{rule|name=Feature Call|text=A call of the form <code>target.feature (...)</code> appearing in a class C is only valid if feature is a feature of the base class of target 's type, and is available to C.}}
The first condition simply expresses that if <code>target</code> has been declared as <code>target: A</code> then <code>feature</code> must be the name of one of the features of <code>A</code>. The second condition reflects Eiffel's application of the principles of information hiding. A <code>feature</code> clause, introducing one or more feature declarations, may appear not only as
@@ -491,7 +497,9 @@ feature {NONE} -- Implementation
-- List of deposits since account's opening.
</code>
This form indicates that the features appearing in that clause are only '''available''' -- in the sense of available for calls, as used in the Feature Call rule -- to the classes listed. In the example feature <code> all_deposits </code> is only available to <code> NONE </code>. Because of the global inheritance structure (page [[5 The Static Picture: System Organization|15]] ) this means it is in fact available to no useful client at all, and is equivalent in practice to <code> feature </code> <code> { </code> <code> } </code> with an empty class list, although the form listing <code> NONE </code> explicitly is more visible and hence preferred.
This form indicates that the features appearing in that clause are only '''available''' -- in the sense of available for calls, as used in the Feature Call rule -- to the classes listed. In the example feature <code> all_deposits </code> is only available to <code> NONE </code>. Because of the [[5 The Static Picture: System Organization#The_global_inheritance_structure|global inheritance structure]], this means it is in fact available to no useful client at all, and is equivalent in practice to <code>feature { }</code> with an empty class list, although the form listing <code> NONE </code> explicitly is more visible and hence preferred.
With this specification a class text including the declaration <code>acc: ACCOUNT</code> and a call of the form
<code>
@@ -505,7 +513,7 @@ Besides fully exported features (introduced by <code> feature ... </code>; witho
feature {A, B, ...}
</code>
for arbitrary classes <code> A, B</code>, ... This enables a group of related classes to provide each other with privileged access, without requiring the introduction of a special module category above the class level (see [[5 The Static Picture: System Organization|"Clusters", page 15]] ).
for arbitrary classes <code>A, B</code>, ... This enables a group of related classes to provide each other with privileged access, without requiring the introduction of a special module category above the class level (see [[5 The Static Picture: System Organization#Clusters|"Clusters"]] ).
Exporting features selectively to a set of classes <code>A, B</code>, ... also makes them available to the descendants of these classes. So a feature clause beginning with just <code>feature</code> is equivalent to one starting with <code>feature {ANY}</code> .