Author:halw

Date:2009-03-27T00:26:37.000000Z


git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@209 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
halw
2009-03-27 00:26:37 +00:00
parent 1644cc9814
commit ac2d81f047
7 changed files with 50 additions and 44 deletions

View File

@@ -6,7 +6,7 @@
These pages are the central repository of information about Eiffel and the products and technologies of Eiffel Software.
The documentation is organized into virtual books. Each book covers an important aspect of the world of Eiffel..
The documentation is organized into virtual books. Each book covers an important aspect of the world of Eiffel.
* [[Guide]] -- Guide to Eiffel Information
* [[Why Eiffel?]] -- Why Eiffel?
@@ -23,32 +23,33 @@ Sources of information on Eiffel include:
===[[Guide]] -- Guide to Eiffel Information===
You are reading this book now.
:You are reading this book now.
===[[Why Eiffel?]] -- Why Eiffel? ===
A summary of the arguments for using Eiffel.
:A summary of the arguments for using Eiffel.
===[[Method|Method and Language]] -- The Eiffel Method and Language===
Materials promoting the understanding of the Eiffel software development method and Eiffel the language.
:Materials promoting the understanding of the Eiffel software development method and Eiffel the language.
===[[EiffelStudio]] -- The EiffelStudio Interactive Development Environment===
Information about installing and using EiffelStudio
:Information about installing and using EiffelStudio
===[[Solutions]] -- Eiffel Solutions, Technologies, and Class Libraries===
Technologies available with Eiffel provide solutions to many ordinary development needs ... and some extraordinary needs too. This book addresses these requirements and the Eiffel technologies that satisfy them.
:Technologies available with Eiffel provide solutions to many ordinary development needs ... and some extraordinary needs too. This book addresses these requirements and the Eiffel technologies that satisfy them.
===[[Platform specifics]] -- Support for particular operating systems===
Although most Eiffel technology is completely platform-independent, Eiffel also provides important platform-specific solutions, described in this book.
:Although most Eiffel technology is completely platform-independent, Eiffel also provides important platform-specific solutions, described in this book.
===[[Community]] -- You can contribute to the documentation!===
:EiffelStudio documentation is available in a convenient Wiki format. This makes it possible to improve the documentation continuously and make sure it is always up to date.
EiffelStudio documentation is available in a convenient Wiki format. This makes it possible to improve the documentation continuously and make sure it is always up to date.
'''Community input''' is welcome. If you are interested in improving and developing EiffelStudio documentation, you can become a ''contributor'' or ''editor'':
@@ -69,28 +70,28 @@ If you are interested in becoming a contributor, please send an email to info@ei
----
===The Eiffel.com website===
===The [http://eiffel.com Eiffel.com] website===
Eiffel Software's website [http://eiffel.com Eiffel.com] contains an enormous amount of information about Eiffel. There are product descriptions, special pages for developers and their managers, case studies and testimonials, the latest Eiffel news, and much more.
----
===Web Presentations on Eiffel.com===
===[http://eiffel.com/developers/presentations/ Web Presentations] on Eiffel.com===
Learn quickly about Eiffel and the things that help make it special, like Design by Contract and EiffelStudio. Learn how Eiffel fits in with and compares to other popular technologies. All this and more is available on the [http://eiffel.com/developers/presentations/ presentations page] on Eiffel.com.
----
===Learning Maps on Eiffel.com===
===[http://eiffel.com/developers/learning_maps/ Learning Maps] on Eiffel.com===
AGet an in-depth view of topics by navigating the [http://eiffel.com/developers/learning_maps/ Eiffel Learning Maps]. Learning maps represent knowledge as a network of interrelated concepts. Attached to the concepts you may find links to additional resources. These resources can be just about anything. You'll find plain text files, web pages, screen shots, and even Eiffel Learnlets. Learnlets are small units of learning in web presentation form that are designed to take no more than 30 minutes to view ... just right for your lunch break.
Get an in-depth view of topics by navigating the [http://eiffel.com/developers/learning_maps/ Eiffel Learning Maps]. Learning maps represent knowledge as a network of interrelated concepts. Attached to the concepts you may find links to additional resources. These resources can be just about anything. You'll find plain text files, web pages, screen shots, and even Eiffel Learnlets. Learnlets are small units of learning in web presentation form that are designed to take no more than 30 minutes to view ... just right for your lunch break.
----
===The EiffelRoom Website===
===The [http://www.eiffelroom.com/ EiffelRoom] Website===
[http://www.eiffelroom.com/ EiffelRoom] is an Eiffel community website on which Eiffel developers from across the globe come together and share their experiences ... and their products. You'll find how-to articles, tips and tricks, example code, whole libraries of EIffel classes, and specialized products. It is easy to contribute to EiffelRoom and start giving back to the community.
@@ -111,7 +112,7 @@ A few times a year, we send out an email newsletter containing announcements of
----
===Object-oriented Software Construction, 2nd Edition===
===[http://www.eiffel.com/doc/oosc/ Object-oriented Software Construction, 2nd Edition]===
There is no better place to gain an in-depth understanding of the Eiffel software development method than [http://www.eiffel.com/doc/oosc/ Object-oriented Software Construction, 2nd Edition], by Bertrand Meyer, published by Prentice Hall. It is the world's most complete guide to building great object-oriented software.
@@ -129,11 +130,11 @@ Eiffel has been standardized under ECMA and ISO. The comprehensive description o
You can help Eiffel by contributing your time, expertise, and products. Here are some websites that you can visit to see what's up with the development of Eiffel Software products.
====dev.eiffel.com====
====[http://dev.eiffel.com dev.eiffel.com]====
:This [http://dev.eiffel.com wiki site] is the hub of development activity for the EiffelStudio interactive development environment. Even if you do not plan to contribute, dev.eiffel.com is a valuable source of information concerning where EiffelStudio is going ... and, if you're curious, where it has been.
====EiffelStudio on Origo====
====[http://eiffelstudio.origo.ethz.ch/ EiffelStudio on Origo]====
:[http://eiffelstudio.origo.ethz.ch/ EiffelStudio on Origo] contains blogs and forums focusing on Eiffel and EiffelStudio topics.

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,3 @@
title=tutorial-4
author=halw
path=content/tutorial-4

View File

@@ -161,7 +161,7 @@ But of course for an incorrect system the best way to find out where the bug is
* <code>all</code> : same as <code>invariant</code>, plus <code>check</code> instructions, loop invariants and loop variants.
An assertion violation, if detected at run time under one of these options other than the first, will cause an exception ( [[8 Design by Contract (tm), Assertions and Exceptions#exception_handling|"Exception handling"]] ). Unless the software has an explicit "retry" plan as explained in the discussion of exceptions, the violation will cause produce an exception trace and cause termination (or, in EiffelStudio, a return to the environment's browsing and debugging facilities at the point of failure). If present, the label of the violated sub clause will be displayed, to help identify the problem.
An assertion violation, if detected at run time under one of these options other than the first, will cause an exception ( [[8 Design by Contract (tm), Assertions and Exceptions#exception_handling|"Exception handling"]] ). Unless the software has an explicit "retry" plan as explained in the discussion of exceptions, the violation will produce an exception trace and cause termination (or, in EiffelStudio, a return to the environment's browsing and debugging facilities at the point of failure). If present, the label of the violated sub clause will be displayed, to help identify the problem.
The default is <code>require</code>. This is particularly interesting in connection with the Eiffel method's insistence on reuse: with libraries such as EiffelBase, richly equipped with preconditions expressing terms of use, an error in the '''client software''' will often lead, for example through an incorrect argument, to violating one of these preconditions. A somewhat paradoxical consequence is that even an application developer who does not apply the method too well (out of carelessness, haste, indifference or ignorance) will still benefit from the presence of contracts in someone else's library code.
@@ -205,7 +205,7 @@ invariant
end -- class interface ACCOUNT
</code>
The words <code>interface class</code> are used instead of just <code>class</code> to avoid any confusion with actual Eiffel text, since this is documentation, not executable software. (It is in fact possible to generate a compilable variant of the Contract Form in the form of a deferred class, a notion defined later.)
The words <code>class interface</code> are used instead of just <code>class</code> to avoid any confusion with actual Eiffel text, since this is documentation, not executable software. (It is in fact possible to generate a compilable variant of the Contract Form in the form of a deferred class, a notion defined later.)
Compared to the full text, the Contract Form of a class (also called its "short form") retains all its interface properties, relevant to client authors: <br/>
* Names and signatures (argument and result type information) for exported features.
@@ -234,7 +234,7 @@ The Contract Form -- or its variant the Flat-Contract Form, which takes account
Another application of Design by Contract&#153; governs the handling of unexpected cases. The vagueness of many discussions of this topic follows from the lack of a precise definition of terms such as "exception". With Design by Contract&#153; we are in a position to be specific: <br/>
* Any routine has a contract to achieve.
* Its body defines a strategy to achieve it -- a sequence of operations, or some other control structure involving operations. Some of these operations are calls to routines, with their own contracts; but even an atomic operation, such as the computation of an arithmetic operation, has an implicit contract, stating that the result will be representable.
* Any one of these operations may <code>fail</code>, that is to say be unable to meet its contract; for example an arithmetic operation may produce an overflow (a on-representable result).
* Any one of these operations may <code>fail</code>, that is to say be unable to meet its contract; for example an arithmetic operation may produce an overflow (a non-representable result).
* The failure of an operation is an '''exception''' for the routine that needed the operation.
* As a result the routine may fail too -- causing an exception in its own caller.
@@ -319,7 +319,7 @@ Concretely, exceptions may result from the following events: <br/>
* Operating system signal:arithmetic overfolow; no memory available for a requested creation or twin -- even after garbage collection has rummaged everything to find some space. (But no C/C++-like "wrong pointer address", which cannot occur thanks to the statically typed nature of Eiffel.)
It is sometimes useful, when handling exceptions in <code>rescue</code> clauses, to ascertain the exact nature of the exception that got the execution there. For this it is suffices to inherit from the Kernel Library class <code>EXCEPTIONS</code>, which provides queries such as <code>exception</code>, giving the code for the last exception, and symbolic names ( [[10 Other Mechanisms#Constant_attributes|"Constant attributes"]] ) for all such codes, such as <code>No_more_memory</code>. You can then process different exceptions differently by testing <code>exception</code> against various possibilities. The method strongly suggests, however, that exception handling code should remain simple; a complicated algorithm in a <code>rescue</code> clause is usually a sign that the mechanism is being misused. Class <code>EXCEPTIONS</code> also provides various facilities for fine-tuning the exception facilities, such as a procedure <code>raise</code> that will explicitly trigger a "developer exception" with a code than can then be detected and processed. Exception handling helps produce Eiffel software that is not just correct but robust, by planning for cases that should not normally arise, but might out of Murphy's law, and ensuring they do not affect the software's basic safety and simplicity.
It is sometimes useful, when handling exceptions in <code>rescue</code> clauses, to ascertain the exact nature of the exception that got the execution there. For this it is suffices to inherit from the Kernel Library class <code>EXCEPTIONS</code>, which provides queries such as <code>exception</code>, giving the code for the last exception, and symbolic names ( [[10 Other Mechanisms#Constant_attributes|"Constant attributes"]] ) for all such codes, such as <code>No_more_memory</code>. You can then process different exceptions differently by testing <code>exception</code> against various possibilities. The method strongly suggests, however, that exception handling code should remain simple; a complicated algorithm in a <code>rescue</code> clause is usually a sign that the mechanism is being misused. Class <code>EXCEPTIONS</code> also provides various facilities for fine-tuning the exception facilities, such as a procedure <code>raise</code> that will explicitly trigger a "developer exception" with a code that can then be detected and processed. Exception handling helps produce Eiffel software that is not just correct but robust, by planning for cases that should not normally arise, but might out of Murphy's law, and ensuring they do not affect the software's basic safety and simplicity.
==Other applications of Design by Contract&#153;==

View File

@@ -405,13 +405,7 @@ Assignment uses the symbol <code> := </code>. The assignment instruction
x := y
</code>
updates the value of <code>x</code> to be the same as that of <code>y</code>. This means that:
[[Image:tutorial-9]]
For entities of reference types, the value of <code>x</code> will be a void reference if the value of <code>y</code> is void, and otherwise <code>x</code> will be attached to the same object OBJ2 as <code>y</code>:
updates the value of <code>x</code> to be the same as that of <code>y</code>. This means that for entities of reference types, the value of <code>x</code> will be a void reference if the value of <code>y</code> is void, and otherwise <code>x</code> will be attached to the same object OBJ2 as <code>y</code>:
[[Image:tutorial-9]]
@@ -423,7 +417,7 @@ 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>.
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 of the assignment <code>x := y</code>.
An operation performing similar duty to <code>copy</code> is <code>twin</code> . The assignment
<code>
@@ -600,13 +594,13 @@ From then on only two events can change the current object and current procedure
In a call of the form <code>target.routine (...)</code> , <code>target</code> denotes a certain object TC. (If not, that is to say, if the value of target is void, attempting to execute the call will trigger an exception, as studied below.) The generating class of TC must, as per the Feature Call rule, contain a routine of name <code>routine</code>. As the call starts, TC becomes the new current object and <code>routine</code> 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 just before the terminated call, were the current object and the current routine -- assume again the role of current object and 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.
The only exception to the last rule is termination of the original root procedure call; in this case the entire execution terminates.
==Abstraction==
The description of assignments stated that in <code>x := y</code> the target <code>x</code> must be an entity. More precisely it must be a '''writable''' entity. This notion excludes formal routine arguments: as noted, a routine <code>r (arg: SOME_TYPE)</code> may assign to <code>arg</code> (reattaching it to a different object), although it can change the attached objects through calls of the form <code>arg.procedure (...)</code> .
The description of assignments stated that in <code>x := y</code> the target <code>x</code> must be an entity. More precisely it must be a '''writable''' entity. This notion excludes formal routine arguments: as noted, a routine <code>r (arg: SOME_TYPE)</code> may not assign to <code>arg</code> (reattaching it to a different object), although it can change the attached objects through calls of the form <code>arg.procedure (...)</code> .
Restricting assignment targets to entities precludes assignments of the form <code>obj.some_attribute := some_value</code> , since the left-hand side <code>obj.some_attribute</code> is an expression (a feature call), not an entity: you may no more assign to <code>obj.some_attribute</code> than to, say, <code>b + a</code> -- another expression that is also, formally, a feature call.

View File

@@ -26,7 +26,7 @@ This makes <code>D</code> an heir of <code>A</code>, <code>B</code> and any othe
{{note|This discussion will rely on the terminology introduced in [[5 The Static Picture: System Organization|The Static Picture: System Organization]]: descendants of a class are the class itself, its heirs, the heirs of its heirs and so on. Proper descendants exclude the class itself. The reverse notions are ancestors and proper ancestors. }}
By default <code>D</code> will simply include all the original features of <code>A</code>, <code>B</code>, ..., to which it may add its own through its <code>feature</code> clauses if any. But the inheritance mechanism is more flexible, allowing <code>D</code> to adapt the inherited features in many ways. Each parent name -- <code>A</code>, <code>B</code>, ... in the example -- can be followed by a Feature Adaptation clause, with subclauses, all optional, introduced by keywords <code>rename</code>, <code>export</code>, <code>undefine</code>, <code>redefine</code> and <code>select</code>, enabling the author of <code>A</code> to make the best use of the inheritance mechanism by tuning the inherited features to the precise needs of <code>D</code>. This makes inheritance a principal tool in the Eiffel process, mentioned earlier, of carefully crafting each individual class, like a machine, for the benefit of its clients. The next sections review the various Feature Adaptation subclauses.
By default <code>D</code> will simply include all the original features of <code>A</code>, <code>B</code>, ..., to which it may add its own through its <code>feature</code> clauses if any. But the inheritance mechanism is more flexible, allowing <code>D</code> to adapt the inherited features in many ways. Each parent name -- <code>A</code>, <code>B</code>, ... in the example -- can be followed by a Feature Adaptation clause, with subclauses, all optional, introduced by keywords <code>rename</code>, <code>export</code>, <code>undefine</code>, <code>redefine</code> and <code>select</code>, enabling the author of <code>D</code> to make the best use of the inheritance mechanism by tuning the inherited features to the precise needs of <code>D</code>. This makes inheritance a principal tool in the Eiffel process, mentioned earlier, of carefully crafting each individual class, like a machine, for the benefit of its clients. The next sections review the various Feature Adaptation subclauses.
==Redefinition==
@@ -73,7 +73,7 @@ end -- class SAVINGS_ACCOUNT
Without the <code>redefine</code> subclause, the declaration of <code>deposit</code> would be invalid, yielding two features of the same name, the inherited one and the new one. The subclause makes this valid by specifying that the new declaration will override the old one.
In a redefinition, the original version -- such as the <code>ACCOUNT</code> implementation of <code>deposit</code> in this example -- is called the <code>precursor</code> of the new version. It is common for a redefinition to rely on the precursor's algorithm and add some other actions; the reserved word <code>Precursor</code> helps achieve this goal simply. Permitted only in a routine redefinition, it denotes the parent routine being redefined. So here he body of the new <code>deposit</code> (called "implementation New" above) could be of the form
In a redefinition, the original version -- such as the <code>ACCOUNT</code> implementation of <code>deposit</code> in this example -- is called the <code>precursor</code> of the new version. It is common for a redefinition to rely on the precursor's algorithm and add some other actions; the reserved word <code>Precursor</code> helps achieve this goal simply. Permitted only in a routine redefinition, it denotes the parent routine being redefined. So here the body of the new <code>deposit</code> (called "New implementation" above) could be of the form
<code>
Precursor (sum)
-- Apply ACCOUNT's version of deposit
@@ -87,7 +87,7 @@ Besides changing the implementation of a routine, a redefinition can turn an arg
==Polymorphism==
The inheritance mechanism is relevant to both roles of classes: module and type. Its application as a mechanism to reuse, adapt and extend features from one class to another, as just seen, covers its role as a '''module extension''' mechanism. But it's also a '''subtyping''' mechanism. To say that <code>D</code> is an heir of <code>A</code>, or more generally a descendant of <code>A</code>, is to expresses that instances of <code>D</code> can be viewed as instances of <code>A</code>.
The inheritance mechanism is relevant to both roles of classes: module and type. Its application as a mechanism to reuse, adapt and extend features from one class to another, as just seen, covers its role as a '''module extension''' mechanism. But it's also a '''subtyping''' mechanism. To say that <code>D</code> is an heir of <code>A</code>, or more generally a descendant of <code>A</code>, is to express that instances of <code>D</code> can be viewed as instances of <code>A</code>.
'''Polymorphic assignment''' supports this second role. In an assignment <code>x := y</code>, the types of <code>x</code> and <code>y</code> do not have, with inheritance, to be identical; the rule is that the type of <code>y</code> must simply '''conform''' to the type of <code>x</code>. A class <code>D</code> conforms to a class <code>A</code> if and only if it is a descendant of <code>A</code> (which includes the case in which <code>A</code> and <code>D</code> are the same class); if these classes are generic, conformance of <code>D</code> <code>[</code> <code>U</code> <code>]</code> to <code>C</code> <code>[</code> <code>T</code> <code>]</code> requires in addition that type <code>U</code> conform to type <code>T</code> (through the recursive application of the same rules).
@@ -122,11 +122,11 @@ A consequence of polymorphism is the ability to define '''polymorphic data struc
accounts: LIST [ACCOUNT]
</code>
the procedure call <code>accounts.extend</code> ( <code>acc</code>), because it uses a procedure <code>extend</code>which in this case expects an argument of any type conforming to <code>ACCOUNT</code>, will be valid not only if <code>acc</code> is of type <code>ACCOUNT</code> but also if it is of a descendant type such as <code>SAVINGS_ACCOUNT</code>. Successive calls of this kind make it possible to construct a data structure that, at run-time, might contain objects of several types, all conforming to <code>ACCOUNT</code>:
the procedure call <code>accounts.extend</code> ( <code>acc</code>), because it uses a procedure <code>extend</code> which in this case expects an argument of any type conforming to <code>ACCOUNT</code>, will be valid not only if <code>acc</code> is of type <code>ACCOUNT</code> but also if it is of a descendant type such as <code>SAVINGS_ACCOUNT</code>. Successive calls of this kind make it possible to construct a data structure that, at run-time, might contain objects of several types, all conforming to <code>ACCOUNT</code>:
[[Image:tutorial-10]] [[Image:tutorial-11]]
Such polymorphic data structures combine the flexibility and safety of genericity and inheritance. You can make them more or less general by choosing for the actual generic parameter, here <code>ACCOUNT</code>, a type higher or lower in the inheritance hierarchy. Static typing is again essential here, prohibiting for example a mistaken insertion of the form <code>accounts.extend (dep)</code> where <code>dep</code>is of type <code>DEPOSIT</code>, which does not conform to <code>ACCOUNT</code>.
Such polymorphic data structures combine the flexibility and safety of genericity and inheritance. You can make them more or less general by choosing for the actual generic parameter, here <code>ACCOUNT</code>, a type higher or lower in the inheritance hierarchy. Static typing is again essential here, prohibiting for example a mistaken insertion of the form <code>accounts.extend (dep)</code> where <code>dep</code> is of type <code>DEPOSIT</code>, which does not conform to <code>ACCOUNT</code>.
At the higher (most abstract) end of the spectrum, you can produce an unrestrictedly polymorphic data structure <code>general_list: LIST [ANY]</code> which makes the call <code>general_list.extend (x)</code> valid for any <code>x</code>. The price to pay is that retrieving an element from such a structure will yield an object on which the only known applicable operations are the most general ones, valid for all types: assignment, copy, twin, equality comparison and others from <code>ANY</code>. Assignment attempt, studied below, will make it possible to apply more specific operations after checking dynamically that a retrieved object is of the appropriate type.
@@ -211,7 +211,7 @@ feature -- Element change
end -- class LIST
</code>
A deferred feature (considered to be a routine, although it can yield an attribute in a proper descendant) has the single keyword <code>deferred</code> in lieu of the <code>do</code> ''Instructions'' clause of an effective routine. A deferred class -- defined as a class that has at least one deferred feature -- must be introduced by <code>class deferred</code> instead of just <code>class</code>.
A deferred feature (considered to be a routine, although it can yield an attribute in a proper descendant) has the single keyword <code>deferred</code> in lieu of the <code>do</code> ''Instructions'' clause of an effective routine. A deferred class -- defined as a class that has at least one deferred feature -- must be introduced by <code>deferred class</code> instead of just <code>class</code>.
As the example of <code>extend</code> shows, a deferred feature, although it has no implementation, can be equipped with assertions. They will be binding on implementations in descendants, in a way to be explained below.
@@ -341,9 +341,9 @@ Some deferred classes describe a structural property, useful to the description
<code>NUMERIC</code> describes objects on which arithmetic operations <code>+, -, *, /</code> are available, with the properties of a ring (associativity, distributivity, zero elements etc.). Kernel Library classes such as <code>INTEGER</code> and <code>REAL</code> -- but not, for example, <code>STRING</code> -- are descendants of <code>NUMERIC</code>. An application that defines a class <code>MATRIX</code> may also make it a descendant of <code>NUMERIC</code>.
<code>COMPARABLE</code> describes objects on which comparison operations <code><, <=, >, >=</code> are available, with the properties of a total preorder (transitivity, irreflexivity). Kernel Library classes such as <code>CHARACTER</code>, <code>STRING</code> and <code>INTEGER</code> -- but not out <code>MATRIX</code> example -- are descendants of <code>NUMERIC</code>.
<code>COMPARABLE</code> describes objects on which comparison operations <code><, <=, >, >=</code> are available, with the properties of a total preorder (transitivity, irreflexivity). Kernel Library classes such as <code>CHARACTER</code>, <code>STRING</code> and <code>INTEGER</code> -- but not our <code>MATRIX</code> example -- are descendants of <code>NUMERIC</code>.
For such classes it is again essential to permit effective features in a deferred class, and to include assertions. For example class <code>COMPARABLE</code> declares <code>infix "<"</code> as deferred, and expresses <code>>, >=</code> and <code><</code> effectively in terms of it.
For such classes it is again essential to permit effective features in a deferred class, and to include assertions. For example class <code>COMPARABLE</code> declares <code>infix "<"</code> as deferred, and expresses <code>>, >=</code> and <code><=</code> effectively in terms of it.
{{note|The type <code>like Current</code> will be explained in [[9 Inheritance#Covariance_and_anchored_declarations|"Covariance and anchored declarations"]] ; you may understand it, in the following class, as equivalent to <code>COMPARABLE</code>. }}
<code>
@@ -452,14 +452,22 @@ As a result of dynamic binding, a call <code>a1</code> . <code>r</code> from a c
The problem is to keep subcontractors honest. Assuming preconditions and postconditions as shown on the last figure, a call in <code>C</code> of the form
<code>
if a1.pre then a1.r end
if a1.pre then
a1.r
end
</code>
or just <code>a1.q</code>; <code>a1.r</code> where the postcondition of <code>q</code> implies the precondition <code>pre</code> of <code>r</code>, satisfies the terms of the contract and hence is entitled to being handled correctly -- to terminate in a state satisfying <code>a1</code> . <code>post</code>. But if we let the subcontractor <code>B</code> redefine the assertions to arbitrary ''pre'' <code>'</code> and ''post''', this is not necessarily the case: ''pre''' could be stronger than ''pre'', enabling <code>B</code> not to process correctly certain calls that are correct from <code>A</code>'s perspective; and ''post''' could be weaker than ''post'', enabling <code>B</code> to do less of a job than advertized for <code>r</code> in the Contract Form of <code>A</code>, the only official reference for authors of client classes such as <code>C</code>. (An assertion <code>p</code> is stronger than or equal to an assertion <code>q</code> if <code>p</code> implies <code>q</code> in the sense of boolean implication.)
or possibly
<code>
a1.q
a1.r
</code>
The rule, then, is that for the redefinition to be correct the new precondition ''pre''' must be weaker than or equal to the original ''pre'', and the new postcondition ''post''' must be stronger than or equal to the original ''post'''.
where the postcondition of some routine <code>q</code> implies the precondition <code>pre</code> of <code>r</code>, satisfies the terms of the contract and hence is entitled to being handled correctly -- to terminate in a state satisfying <code>a1</code>.<code>post</code>. But if we let the subcontractor <code>B</code> redefine the assertions to arbitrary ''pre' ''and ''post','' this is not necessarily the case: ''pre' ''could be stronger than ''pre'', enabling <code>B</code> not to process correctly certain calls that are correct from <code>A</code>'s perspective; and ''post' ''could be weaker than ''post'', enabling <code>B</code> to do less of a job than advertized for <code>r</code> in the Contract Form of <code>A</code>, the only official reference for authors of client classes such as <code>C</code>. (An assertion <code>p</code> is stronger than or equal to an assertion <code>q</code> if <code>p</code> implies <code>q</code> in the sense of boolean implication.)
Because it is impossible to check simply that an assertion is weaker or stronger than another, the language rule relies on different forms of the assertion constructs, <code>else require</code> and <code>then ensure</code>, for redeclared routines. They rely on the mathematical property that, for any assertions <code>p</code> and <code>q,</code> <code>p implies ( p or q )</code>, and <code>(p and q) implies p</code>. For a precondition, using <code>else require</code> with a new assertion will perform an <code>or</code>, which can only weaken the original; for a postcondition, <code>then ensure</code> will perform an <code>and</code>, which can only strengthen the original. Hence the rule:
The rule, then, is that for the redefinition to be correct the new precondition ''pre' ''must be weaker than or equal to the original ''pre'', and the new postcondition ''post' ''must be stronger than or equal to the original ''post''.
Because it is impossible to check simply that an assertion is weaker or stronger than another, the language rule relies on different forms of the assertion constructs, <code>else require</code> and <code>then ensure</code>, for redeclared routines. They rely on the mathematical property that, for any assertions <code>p</code> and <code>q,</code> <code>p implies (p or q)</code>, and <code>(p and q) implies p</code>. For a precondition, using <code>require else</code> with a new assertion will perform an <code>or</code>, which can only weaken the original; for a postcondition, <code>ensure then</code> will perform an <code>and</code>, which can only strengthen the original. Hence the rule:
{{rule|name=Assertion Redeclaration|text=In the redeclared version of a routine, it is not permitted to use a require or ensure clause. Instead you may: Introduce a new condition with require else, for or-ing with the original precondition. Introduce a new condition with ensure then, for and-ing with the original postcondition. In the absence of such a clause, the original assertions are retained. }}

View File

@@ -35,7 +35,7 @@ The client relation can be cyclic; an example involving a cycle would be classes
In modeling terms, client roughly represents the relation "has" and heir roughly represents "is". For example we may use Eiffel classes to model a certain system and express that every child <code>has</code> a birth date (client relation) and is a person (inheritance).
Distinctive of Eiffel is the rule that lasses can only be connected through these two relations. This excludes the behind-the-scenes dependencies often found in other approaches, such as the use of global variables, which jeopardize the modularity of a system. Only through a strict policy of limited and explicit inter-class relations can we achieve the goals of reusability and extendibility.
Distinctive of Eiffel is the rule that classes can only be connected through these two relations. This excludes the behind-the-scenes dependencies often found in other approaches, such as the use of global variables, which jeopardize the modularity of a system. Only through a strict policy of limited and explicit inter-class relations can we achieve the goals of reusability and extendibility.
==The global inheritance structure==
@@ -66,7 +66,7 @@ The subsequent sections will show how to write Eiffel classes with their feature
end
</code>
to indicate that it is actually an encapsulation of a C function whose original name is <code>fstat _</code>. The <code>alias</code> clause is optional, but here it is needed because the C name, starting with an underscore, is not valid as an Eiffel identifier.
to indicate that it is actually an encapsulation of a C function whose original name is <code>_fstat</code>. The <code>alias</code> clause is optional, but here it is needed because the C name, starting with an underscore, is not valid as an Eiffel identifier.
Similar syntax exists to interface with C++ classes. EiffelStudio includes a tool called Legacy++ which will automatically produce, from a C++ class, an Eiffel class that encapsulates its facilities, making them available to the rest of the Eiffel software as bona fide Eiffel features.