Author:halw

Date:2008-12-15T21:23:45.000000Z


git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@139 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
halw
2008-12-15 21:23:45 +00:00
parent df0e7e8976
commit b8588abd09
8 changed files with 580 additions and 584 deletions

View File

@@ -41,7 +41,7 @@ Presenting the names in this format handles the conflicts of overloading and pro
===Eiffel Creation Procedures as Constructors?=== ===Eiffel Creation Procedures as Constructors?===
Eiffel creation procedures do not map to constructors when Eiffel classes are compiled into assemblies. Rather, they are actually manifested as functions on a factory class in the namespace <code> Create </code> in the assembly. These functions return an initialized instance. In the section Type Organization there is more information about the organization of the types in assemblies built with Eiffel for .NET, along with an example of using types from such an assembly. Eiffel creation procedures do not map to constructors when Eiffel classes are compiled into assemblies. Rather, they are actually manifested as functions on a factory class in the namespace <code lang=text>Create</code> in the assembly. These functions return an initialized instance. In the section Type Organization there is more information about the organization of the types in assemblies built with Eiffel for .NET, along with an example of using types from such an assembly.

View File

@@ -161,7 +161,7 @@ Because Eiffel does not support properties directly, the propertiesof typeswhich
In order to ask for the property's current value (technically, receiving the result of the property's <code>get</code> routine), a query feature is generated for the property. The query will be namedthe Eiffel name of the property. In order to ask for the property's current value (technically, receiving the result of the property's <code>get</code> routine), a query feature is generated for the property. The query will be namedthe Eiffel name of the property.
As noted above, setting the value of a property cannot be done in Eiffel as it is done in C# and VB.NET because Eiffel disallows assignments of the form <code>x</code>. <code>f</code> := <code>y</code>. So, for each writable property, an Eiffel command feature is available to set the value of the property. The name for this command will be <code>set_</code> followed by the Eiffel name for the property. As noted above, setting the value of a property cannot be done in Eiffel as it is done in C# and VB.NET because Eiffel disallows assignments of the form <code>x</code>.<code>f</code> := <code>y</code>. So, for each writable property, an Eiffel command feature is available to set the value of the property. The name for this command will be "<code>set_</code>" followed by the Eiffel name for the property.
As a result, the code for using a .NET property looks very much like the code to use an Eiffel attribute. In the following code fragment, an instance of the type <code>System.Windows.Forms.Form</code> which is available in Eiffel for .NET as <code>WINFORMS_FORM</code> is used by an Eiffel client. <code>System.Windows.Forms.Form</code> has a property <code>Text</code> which is of type <code>System.String</code>. Here the <code>Text</code> property is being set using the <code>set_text</code> feature, and then being recalled by using the query <code>text</code>. As a result, the code for using a .NET property looks very much like the code to use an Eiffel attribute. In the following code fragment, an instance of the type <code>System.Windows.Forms.Form</code> which is available in Eiffel for .NET as <code>WINFORMS_FORM</code> is used by an Eiffel client. <code>System.Windows.Forms.Form</code> has a property <code>Text</code> which is of type <code>System.String</code>. Here the <code>Text</code> property is being set using the <code>set_text</code> feature, and then being recalled by using the query <code>text</code>.
<code> <code>

View File

@@ -32,27 +32,29 @@ create
feature -- Initialization feature -- Initialization
make is make
-- Create an empty list. -- Create an empty list.
do do
before := True before := True
ensure is_before: before ensure
is_before: before
end end
feature -- Access feature -- Access
item: G is item: G
-- Current item -- Current item
do do
Result := active.item Result := active.item
end end
first: like item is first: like item
-- Item at first position -- Item at first position
do do
Result := first_element.item Result := first_element.item
end end
(other features omitted)
... other features omitted ...
invariant invariant
before_constraint: before implies (active = first_element) before_constraint: before implies (active = first_element)
@@ -123,13 +125,13 @@ create
feature -- Initialization feature -- Initialization
make is make
-- Creation procedure -- Creation procedure
do do
an_attribute := 5 an_attribute := 5
end end
make_with_arguments (hour: INTEGER; minute: INTEGER; second: INTEGER) is make_with_arguments (hour: INTEGER; minute: INTEGER; second: INTEGER)
-- Another creation procedure -- Another creation procedure
do do
an_attribute := second + (minute * 60) + (hour * 3600) an_attribute := second + (minute * 60) + (hour * 3600)
@@ -140,7 +142,7 @@ feature -- Access
an_attribute: INTEGER an_attribute: INTEGER
-- An attribute of type INTEGER -- An attribute of type INTEGER
another_attribute: INTEGER is 46 another_attribute: INTEGER = 46
-- A constant attribute -- A constant attribute
a_function: STRING is a_function: STRING is
@@ -149,7 +151,7 @@ feature -- Access
Result := an_attribute.out Result := an_attribute.out
end end
another_function (an_int: INTEGER): INTEGER is another_function (an_int: INTEGER): INTEGER
-- A function with arguments -- A function with arguments
do do
Result := an_attribute + an_int Result := an_attribute + an_int
@@ -157,13 +159,13 @@ feature -- Access
feature -- Basic Operations feature -- Basic Operations
a_procedure is a_procedure
-- A procedure with no arguments -- A procedure with no arguments
do do
an_attribute := an_attribute + 5 an_attribute := an_attribute + 5
end end
another_procedure (an_int: INTEGER; another_int: INTEGER) is another_procedure (an_int: INTEGER; another_int: INTEGER)
-- A procedure with arguments -- A procedure with arguments
do do
an_attribute := an_attribute + an_int + another_int an_attribute := an_attribute + an_int + another_int
@@ -185,7 +187,7 @@ When you write a feature in a class, you typically will include some of the foll
Let's dissect one feature and identify its parts: Let's dissect one feature and identify its parts:
<code> <code>
another_function (an_int: INTEGER): INTEGER is another_function (an_int: INTEGER): INTEGER
-- A function with arguments -- A function with arguments
do do
Result := an_attribute + an_int Result := an_attribute + an_int
@@ -201,9 +203,10 @@ In this feature:
* "INTEGER" (after the argument list) is the feature's type. * "INTEGER" (after the argument list) is the feature's type.
* "do " introduces the implementation code. * "do " introduces the implementation code.
* "Result := an_attribute + an_int" is an instruction. * "Result := an_attribute + an_int" is an instruction.
{{note|This feature is a function. As a consequence the computation uses the keyword "Result" as an entity name for the value to be returned by the function }}
* "end" ends the feature declaration {{note|This feature is a function. As a consequence the computation uses the keyword "<eiffel>Result</eiffel>' as an entity name for the value to be returned by the function }}
* "<eiffel>end</eiffel>" ends the feature declaration
==General Structure of Routines== ==General Structure of Routines==
@@ -223,7 +226,7 @@ All of the sections except the Routine Body are optional.
Here is another feature, a routine, which has all of these except obsolete and rescue. Here is another feature, a routine, which has all of these except obsolete and rescue.
<code> <code>
insert_text_header_item (a_label: STRING; insert_text_header_item (a_label: STRING;
a_width, a_format: INTEGER; insert_after_item_no: INTEGER) is a_width, a_format: INTEGER; insert_after_item_no: INTEGER)
-- Insert a text item to the header control -- Insert a text item to the header control
-- after the `insert_item_item_no' item. -- after the `insert_item_item_no' item.
require require
@@ -293,7 +296,7 @@ There are other forms that a routine body can take. Here are some examples of so
====External Routines==== ====External Routines====
<code> <code>
cwin_tooltips_class: POINTER is cwin_tooltips_class: POINTER
external external
"C [macro ] : EIF_POINTER" "C [macro ] : EIF_POINTER"
alias alias
@@ -315,7 +318,7 @@ This is the routine body of a "once" routine, specifically a "once function". A
Once procedures are useful for doing things that for some reason should not be done multiple times. Once procedures are useful for doing things that for some reason should not be done multiple times.
If the once routine is a function (as the example above), it computes the resulting object on the first call, then on subsequent calls, it returns the object it originally created without executing the computation. Once functions facilitate shared objects which helps us in avoiding globals. A class containing a once function can be inherited by many other classes. The first object to apply the once function causes the resulting object to be created and initialized. Subsequent applications by any other object accesses the originally created instance. If the once routine is a function (as the example above), it computes the resulting object on the first call, then on subsequent calls, it returns the object it originally created without executing the computation. Once functions facilitate shared objects which helps us in avoiding global entities. A class containing a once function can be inherited by many other classes. The first object to apply the once function causes the resulting object to be created and initialized. Subsequent applications by any other object accesses the originally created instance.
====Deferred Routines==== ====Deferred Routines====
<code> <code>
@@ -324,7 +327,7 @@ If the once routine is a function (as the example above), it computes the result
The body for a deferred routine is simply the keyword "<code>deferred</code>". Below is the deferred routine body in the context of an entire feature. The body for a deferred routine is simply the keyword "<code>deferred</code>". Below is the deferred routine body in the context of an entire feature.
<code> <code>
set_position (new_position: INTEGER) is set_position (new_position: INTEGER)
-- Set `position' with `new_position' -- Set `position' with `new_position'
require require
exists: exists exists: exists
@@ -350,7 +353,7 @@ The postcondition part of a routine is introduced by the keyword " <code> ensure
Our example feature does not have an explicitly coded rescue part. The rescue, introduced by the keyword "<code>rescue</code>", provides a routine with a chance to do additional processing in the case that it incurs an exeption during normal processing. We will learn about the rescue clause in the section [[Exception Mechanism|Exception Mechanism]] . Until then, you can see what a rescue part looks like in the feature below. Our example feature does not have an explicitly coded rescue part. The rescue, introduced by the keyword "<code>rescue</code>", provides a routine with a chance to do additional processing in the case that it incurs an exeption during normal processing. We will learn about the rescue clause in the section [[Exception Mechanism|Exception Mechanism]] . Until then, you can see what a rescue part looks like in the feature below.
<code> <code>
bind is bind
-- Bind socket to local address in `address'. -- Bind socket to local address in `address'.
require require
socket_exists: exists socket_exists: exists
@@ -386,16 +389,16 @@ feature -- Access
an_attribute: INTEGER an_attribute: INTEGER
-- An attribute of type INTEGER -- An attribute of type INTEGER
another_attribute: INTEGER is 46 another_attribute: INTEGER = 46
-- A constant attribute -- A constant attribute
a_function: STRING is a_function: STRING
-- A function without arguments -- A function without arguments
do do
Result := an_attribute.out Result := an_attribute.out
end end
another_function (an_int: INTEGER): INTEGER is another_function (an_int: INTEGER): INTEGER
-- A function with arguments -- A function with arguments
do do
Result := an_attribute + an_int Result := an_attribute + an_int
@@ -403,20 +406,20 @@ feature -- Access
feature -- Basic Operations feature -- Basic Operations
a_procedure is a_procedure
-- A procedure with no arguments -- A procedure with no arguments
do do
an_attribute := an_attribute + 5 an_attribute := an_attribute + 5
end end
another_procedure (an_int: INTEGER; another_int: INTEGER) is another_procedure (an_int: INTEGER; another_int: INTEGER)
-- A procedure with arguments -- A procedure with arguments
do do
an_attribute := an_attribute + an_int + another_int an_attribute := an_attribute + an_int + another_int
end end
</code> </code>
A feature clause like the ones in the example above means that all the features that follow, until the next feature clause are exported to clients based on any class. Techically, this A feature clause like the ones in the example above means that all the features that follow, until the next feature clause are exported to clients based on any class. Technically, this
<code> <code>
feature -- Basic Operations feature -- Basic Operations
</code> </code>
@@ -509,7 +512,7 @@ But for reference types, that constraint is unnecessarily restrictive. So, for r
end end
</code> </code>
Conditionals in Eiffel use at a minimum the keywords " <code> if </code>", " <code> then </code>", and <code> end </code>".Optionally, they may use the keywords " <code> elseif </code>" and " <code> else </code>". Conditionals in Eiffel use at a minimum the keywords "<code>if</code>", "<code>then</code>", and "<code>end</code>". Optionally, they may use the keywords "<code>elseif</code>" and "<code>else</code>".
===Loop=== ===Loop===
<code> <code>

View File

@@ -45,7 +45,7 @@ create
feature -- Initialization feature -- Initialization
make is make
-- Create an empty list. -- Create an empty list.
do do
before := True before := True
@@ -55,18 +55,19 @@ feature -- Initialization
feature -- Access feature -- Access
item: G is item: G
-- Current item -- Current item
do do
Result := active.item Result := active.item
end end
first: like item is first: like item
-- Item at first position -- Item at first position
do do
Result := first_element.item Result := first_element.item
end end
(other features omitted)
... other features omitted ...
invariant invariant
before_constraint: before implies (active = first_element) before_constraint: before implies (active = first_element)
@@ -149,13 +150,13 @@ Let's take a quick look at object creation. Consider this declaration:
my_list_of_cats: OLD_FASHION_LIST [CAT] my_list_of_cats: OLD_FASHION_LIST [CAT]
</code> </code>
Here the entity <code> my_list_of_cats </code> can be attached to an object of type <code> OLD_FASHION_LIST </code> [ <code> CAT </code>] at runtime. The process of converting <code> my_list_of_cats </code> from holding a void reference to holding a reference to a object modeling a list of cats, starts when a creation instruction is executed. The creation instruction creates the instance and may apply a creation procedure to initialize the instance. A creation instruction for the declaration above would look like this: Here the entity <code>my_list_of_cats</code> can be attached to an object of type <code>OLD_FASHION_LIST [CAT]</code> at runtime. The process of converting <code>my_list_of_cats</code> from holding a void reference to holding a reference to a object modeling a list of cats, starts when a creation instruction is executed. The creation instruction creates the instance and may apply a creation procedure to initialize the instance. A creation instruction for the declaration above would look like this:
<code> <code>
create my_list_of_cats.make create my_list_of_cats.make
</code> </code>
The <code>create</code> keyword is used to introduce a creation instruction. This instruction causes the following four things to happen: The <code>create</code> keyword is used to introduce a creation instruction. This instruction causes the following four things to happen:
* A shell of a new instance of <code> OLD_FASHION_LIST </code> [ <code> CAT </code>] is created in memory with a memory field for every attribute * A shell of a new instance of <code>OLD_FASHION_LIST [CAT]</code> is created in memory with a memory field for every attribute
* Each field is initialized with standard default values * Each field is initialized with standard default values
** False for type <code>BOOLEAN</code> ** False for type <code>BOOLEAN</code>
** Null character for type <code>CHARACTER</code> ** Null character for type <code>CHARACTER</code>
@@ -165,28 +166,29 @@ The <code> create </code> keyword is used to introduce a creation instruction. T
* Attach the new instance to the entity <code>my_list_of_cats</code> * Attach the new instance to the entity <code>my_list_of_cats</code>
* Apply the creation procedure <code>make</code> * Apply the creation procedure <code>make</code>
Once these steps complete successfully, <code> my_list_of_cats </code> will be attached to a valid instance (i.e., an instance in which the class invariant is true) of <code> OLD_FASHIONED_LIST </code> [ <code> CAT </code>]. Once these steps complete successfully, <code>my_list_of_cats</code> will be attached to a valid instance (i.e., an instance in which the class invariant is true) of <code>OLD_FASHIONED_LIST [CAT]</code>.
===Features=== ===Features===
<code> <code>
feature -- Initialization feature -- Initialization
make is make
-- Create an empty list. -- Create an empty list.
do do
before := True before := True
ensure is_before: before ensure
is_before: before
end end
feature -- Access feature -- Access
item: G is item: G
-- Current item -- Current item
do do
Result := active.item Result := active.item
end end
first: like item is first: like item
-- Item at first position -- Item at first position
do do
Result := first_element.item Result := first_element.item
@@ -211,6 +213,7 @@ invariant
after_constraint: after implies (active = last_element) after_constraint: after implies (active = last_element)
</code> </code>
Here's the last word in a class definition ... both literally and figuratively. The invariant part, introduced not surprisingly by the keyword "<code>invariant</code>", is that portion of the class in which we can state what it means for an object to be a valid instance of this class. Here's the last word in a class definition ... both literally and figuratively. The invariant part, introduced not surprisingly by the keyword "<code>invariant</code>", is that portion of the class in which we can state what it means for an object to be a valid instance of this class.
We will learn more about class invariants in the section titled [[Design by Contract and Assertions|Design by Contract and Assertions]] . We will learn more about class invariants in the section titled [[Design by Contract and Assertions|Design by Contract and Assertions]] .

View File

@@ -17,22 +17,19 @@ If the producer wants the class to handle all kinds of things, then the answer m
<code> <code>
class class
LIST_OF_THINGS LIST_OF_THINGS
. ...
.
feature -- Access feature -- Access
item: ANY item: ANY
-- The thing currently pointed to by cursor -- The thing currently pointed to by cursor
. ...
feature -- Element change feature -- Element change
put (new_item: ANY) put (new_item: ANY)
-- Add `new_item' at the end of the list -- Add `new_item' at the end of the list
. ...
.
</code> </code>
This will work, but has some definite disadvantages. Suppose you choose to use this class to maintain a list of cats in one of your classes. You might make this declaration: This will work, but has some definite disadvantages. Suppose you choose to use this class to maintain a list of cats in one of your classes. You might make this declaration:
@@ -44,8 +41,7 @@ This will work, but has some definite disadvantages. Suppose you choose to use t
Then you could add individual instances to the list: Then you could add individual instances to the list:
<code> <code>
fluffy, twinkie: CAT fluffy, twinkie: CAT
. ...
.
my_cats.put (fluffy) my_cats.put (fluffy)
my_cats.put (twinkie) my_cats.put (twinkie)
</code> </code>
@@ -54,8 +50,8 @@ One problem with this type of list is that the type system will not help you kee
<code> <code>
fluffy, twinkie: CAT fluffy, twinkie: CAT
thor: PSYCHOTIC_HYDROPHOBIC_CAT_HATING_DOG thor: PSYCHOTIC_HYDROPHOBIC_CAT_HATING_DOG
. -- A very nasty dog
. ...
my_cats.put (fluffy) my_cats.put (fluffy)
my_cats.put (twinkie) my_cats.put (twinkie)
my_cats.put (thor) my_cats.put (thor)
@@ -69,8 +65,7 @@ Another problem is that to do any <code>CAT</code> things with an item in the li
This is because "item" is type <code>ANY</code> and although it may be currently attached to an instance of <code>CAT</code>, the static typing system cannot guarantee that. So you must use assignment attempt as we saw in the polymorphism example in [[Inheritance|Inheritance]] . This is because "item" is type <code>ANY</code> and although it may be currently attached to an instance of <code>CAT</code>, the static typing system cannot guarantee that. So you must use assignment attempt as we saw in the polymorphism example in [[Inheritance|Inheritance]] .
<code> <code>
some_cat: CAT some_cat: CAT
. ...
.
some_cat ?= my_cats.item some_cat ?= my_cats.item
if some_cat /= Void then if some_cat /= Void then
some_cat.purr some_cat.purr
@@ -89,17 +84,15 @@ In Eiffel this is accomplished through generic classes. Generic classes are writ
<code> <code>
class class
LIST [G] LIST [G]
. ...
.
feature -- Access feature -- Access
item: G item: G
-- The item currently pointed to by cursor -- The item currently pointed to by cursor
. ...
feature -- Element change feature -- Element change
put (new_item: G) put (new_item: G)
-- Add `new_item' at the end of the list -- Add `new_item' at the end of the list
. ...
.
</code> </code>
We could declare feature <code>my_cats</code> as a <code>LIST</code> of items of type <code>CAT</code>. By doing so we are providing <code>CAT</code> as an "actual generic parameter" in the declaration. Then we are free to treat the features of <code>LIST</code> as if the class name <code>CAT</code> had been substituted for every occurrence of the formal generic parameter <code>G</code>. We could declare feature <code>my_cats</code> as a <code>LIST</code> of items of type <code>CAT</code>. By doing so we are providing <code>CAT</code> as an "actual generic parameter" in the declaration. Then we are free to treat the features of <code>LIST</code> as if the class name <code>CAT</code> had been substituted for every occurrence of the formal generic parameter <code>G</code>.
@@ -107,11 +100,10 @@ We could declare feature <code> my_cats </code> as a <code> LIST </code> of item
my_cats: LIST [CAT] my_cats: LIST [CAT]
-- A list of my cats -- A list of my cats
fluffy, twinkie: CAT fluffy, twinkie: CAT
. ...
.
my_cats.put (fluffy) my_cats.put (fluffy)
my_cats.put (twinkie) my_cats.put (twinkie)
. ...
my_cats.item.purr -- Valid now my_cats.item.purr -- Valid now
</code> </code>
@@ -121,10 +113,7 @@ The following would no longer be valid:
-- A list of my cats -- A list of my cats
thor: PSYCHOTIC_HYDROPHOBIC_CAT_HATING_DOG thor: PSYCHOTIC_HYDROPHOBIC_CAT_HATING_DOG
...
.
.
my_cats.put (thor) -- Is invalid my_cats.put (thor) -- Is invalid
</code> </code>

View File

@@ -30,30 +30,30 @@ deferred class
feature -- Comparison feature -- Comparison
infix "<" (other: like Current): BOOLEAN is infix "<" (other: like Current): BOOLEAN
-- Is current object less than `other'? -- Is current object less than `other'?
deferred deferred
end end
infix "<=" (other: like Current): BOOLEAN is infix "<=" (other: like Current): BOOLEAN
-- Is current object less than or equal to `other'? -- Is current object less than or equal to `other'?
do do
Result := not (other < Current) Result := not (other < Current)
end end
infix ">" (other: like Current): BOOLEAN is infix ">" (other: like Current): BOOLEAN
-- Is current object greater than `other'? -- Is current object greater than `other'?
do do
Result := other < Current Result := other < Current
end end
infix ">=" (other: like Current): BOOLEAN is infix ">=" (other: like Current): BOOLEAN
-- Is current object greater than or equal to `other'? -- Is current object greater than or equal to `other'?
do do
Result := not (Current < other) Result := not (Current < other)
end end
is_equal (other: like Current): BOOLEAN is is_equal (other: like Current): BOOLEAN
-- Is `other' attached to an object of the same type -- Is `other' attached to an object of the same type
-- as current object and identical to it? -- as current object and identical to it?
do do
@@ -270,7 +270,8 @@ Armed with these <code> RECTANGLE </code>-specific features, the producer of <co
To implement this specialized version of <code>perimeter</code>, the producer of <code>RECTANGLE</code> must add the feature to the class, but also must list its name in the "<code>redefine</code>" part of the <code>RECTANGLE</code>'s inheritance clause. To implement this specialized version of <code>perimeter</code>, the producer of <code>RECTANGLE</code> must add the feature to the class, but also must list its name in the "<code>redefine</code>" part of the <code>RECTANGLE</code>'s inheritance clause.
<code> <code>
class RECTANGLE class
RECTANGLE
inherit inherit
POLYGON POLYGON
redefine redefine
@@ -279,7 +280,7 @@ inherit
. .
. .
feature feature
perimeter: REAL is perimeter: REAL
-- Sum of lengths of all sides -- Sum of lengths of all sides
do do
Result := 2 * (width + height) Result := 2 * (width + height)