mirror of
https://github.com/EiffelSoftware/eiffel-org.git
synced 2025-12-07 15:22:31 +01:00
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:
@@ -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 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.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
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>.
|
||||
<code>
|
||||
|
||||
@@ -32,27 +32,29 @@ create
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make is
|
||||
make
|
||||
-- Create an empty list.
|
||||
do
|
||||
before := True
|
||||
ensure is_before: before
|
||||
ensure
|
||||
is_before: before
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
item: G is
|
||||
item: G
|
||||
-- Current item
|
||||
do
|
||||
Result := active.item
|
||||
end
|
||||
|
||||
first: like item is
|
||||
first: like item
|
||||
-- Item at first position
|
||||
do
|
||||
Result := first_element.item
|
||||
end
|
||||
(other features omitted)
|
||||
|
||||
... other features omitted ...
|
||||
|
||||
invariant
|
||||
before_constraint: before implies (active = first_element)
|
||||
@@ -123,13 +125,13 @@ create
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make is
|
||||
make
|
||||
-- Creation procedure
|
||||
do
|
||||
an_attribute := 5
|
||||
end
|
||||
|
||||
make_with_arguments (hour: INTEGER; minute: INTEGER; second: INTEGER) is
|
||||
make_with_arguments (hour: INTEGER; minute: INTEGER; second: INTEGER)
|
||||
-- Another creation procedure
|
||||
do
|
||||
an_attribute := second + (minute * 60) + (hour * 3600)
|
||||
@@ -140,7 +142,7 @@ feature -- Access
|
||||
an_attribute: INTEGER
|
||||
-- An attribute of type INTEGER
|
||||
|
||||
another_attribute: INTEGER is 46
|
||||
another_attribute: INTEGER = 46
|
||||
-- A constant attribute
|
||||
|
||||
a_function: STRING is
|
||||
@@ -149,7 +151,7 @@ feature -- Access
|
||||
Result := an_attribute.out
|
||||
end
|
||||
|
||||
another_function (an_int: INTEGER): INTEGER is
|
||||
another_function (an_int: INTEGER): INTEGER
|
||||
-- A function with arguments
|
||||
do
|
||||
Result := an_attribute + an_int
|
||||
@@ -157,13 +159,13 @@ feature -- Access
|
||||
|
||||
feature -- Basic Operations
|
||||
|
||||
a_procedure is
|
||||
a_procedure
|
||||
-- A procedure with no arguments
|
||||
do
|
||||
an_attribute := an_attribute + 5
|
||||
end
|
||||
|
||||
another_procedure (an_int: INTEGER; another_int: INTEGER) is
|
||||
another_procedure (an_int: INTEGER; another_int: INTEGER)
|
||||
-- A procedure with arguments
|
||||
do
|
||||
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:
|
||||
<code>
|
||||
another_function (an_int: INTEGER): INTEGER is
|
||||
another_function (an_int: INTEGER): INTEGER
|
||||
-- A function with arguments
|
||||
do
|
||||
Result := an_attribute + an_int
|
||||
@@ -201,9 +203,10 @@ In this feature:
|
||||
* "INTEGER" (after the argument list) is the feature's type.
|
||||
* "do " introduces the implementation code.
|
||||
* "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==
|
||||
|
||||
@@ -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.
|
||||
<code>
|
||||
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
|
||||
-- after the `insert_item_item_no' item.
|
||||
require
|
||||
@@ -293,7 +296,7 @@ There are other forms that a routine body can take. Here are some examples of so
|
||||
|
||||
====External Routines====
|
||||
<code>
|
||||
cwin_tooltips_class: POINTER is
|
||||
cwin_tooltips_class: POINTER
|
||||
external
|
||||
"C [macro ] : EIF_POINTER"
|
||||
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.
|
||||
|
||||
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====
|
||||
<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.
|
||||
<code>
|
||||
set_position (new_position: INTEGER) is
|
||||
set_position (new_position: INTEGER)
|
||||
-- Set `position' with `new_position'
|
||||
require
|
||||
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.
|
||||
<code>
|
||||
bind is
|
||||
bind
|
||||
-- Bind socket to local address in `address'.
|
||||
require
|
||||
socket_exists: exists
|
||||
@@ -386,16 +389,16 @@ feature -- Access
|
||||
an_attribute: INTEGER
|
||||
-- An attribute of type INTEGER
|
||||
|
||||
another_attribute: INTEGER is 46
|
||||
another_attribute: INTEGER = 46
|
||||
-- A constant attribute
|
||||
|
||||
a_function: STRING is
|
||||
a_function: STRING
|
||||
-- A function without arguments
|
||||
do
|
||||
Result := an_attribute.out
|
||||
end
|
||||
|
||||
another_function (an_int: INTEGER): INTEGER is
|
||||
another_function (an_int: INTEGER): INTEGER
|
||||
-- A function with arguments
|
||||
do
|
||||
Result := an_attribute + an_int
|
||||
@@ -403,20 +406,20 @@ feature -- Access
|
||||
|
||||
feature -- Basic Operations
|
||||
|
||||
a_procedure is
|
||||
a_procedure
|
||||
-- A procedure with no arguments
|
||||
do
|
||||
an_attribute := an_attribute + 5
|
||||
end
|
||||
|
||||
another_procedure (an_int: INTEGER; another_int: INTEGER) is
|
||||
another_procedure (an_int: INTEGER; another_int: INTEGER)
|
||||
-- A procedure with arguments
|
||||
do
|
||||
an_attribute := an_attribute + an_int + another_int
|
||||
end
|
||||
</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>
|
||||
feature -- Basic Operations
|
||||
</code>
|
||||
@@ -509,7 +512,7 @@ But for reference types, that constraint is unnecessarily restrictive. So, for r
|
||||
end
|
||||
</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===
|
||||
<code>
|
||||
|
||||
@@ -45,7 +45,7 @@ create
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make is
|
||||
make
|
||||
-- Create an empty list.
|
||||
do
|
||||
before := True
|
||||
@@ -55,18 +55,19 @@ feature -- Initialization
|
||||
|
||||
feature -- Access
|
||||
|
||||
item: G is
|
||||
item: G
|
||||
-- Current item
|
||||
do
|
||||
Result := active.item
|
||||
end
|
||||
|
||||
first: like item is
|
||||
first: like item
|
||||
-- Item at first position
|
||||
do
|
||||
Result := first_element.item
|
||||
end
|
||||
(other features omitted)
|
||||
|
||||
... other features omitted ...
|
||||
|
||||
invariant
|
||||
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]
|
||||
</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>
|
||||
create my_list_of_cats.make
|
||||
</code>
|
||||
|
||||
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
|
||||
** False for type <code>BOOLEAN</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>
|
||||
* 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===
|
||||
<code>
|
||||
feature -- Initialization
|
||||
|
||||
make is
|
||||
make
|
||||
-- Create an empty list.
|
||||
do
|
||||
before := True
|
||||
ensure is_before: before
|
||||
ensure
|
||||
is_before: before
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
item: G is
|
||||
item: G
|
||||
-- Current item
|
||||
do
|
||||
Result := active.item
|
||||
end
|
||||
|
||||
first: like item is
|
||||
first: like item
|
||||
-- Item at first position
|
||||
do
|
||||
Result := first_element.item
|
||||
@@ -211,6 +213,7 @@ invariant
|
||||
after_constraint: after implies (active = last_element)
|
||||
</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.
|
||||
|
||||
We will learn more about class invariants in the section titled [[Design by Contract and Assertions|Design by Contract and Assertions]] .
|
||||
|
||||
@@ -17,22 +17,19 @@ If the producer wants the class to handle all kinds of things, then the answer m
|
||||
<code>
|
||||
class
|
||||
LIST_OF_THINGS
|
||||
.
|
||||
.
|
||||
|
||||
...
|
||||
feature -- Access
|
||||
|
||||
item: ANY
|
||||
-- The thing currently pointed to by cursor
|
||||
|
||||
.
|
||||
...
|
||||
|
||||
feature -- Element change
|
||||
|
||||
put (new_item: ANY)
|
||||
-- Add `new_item' at the end of the list
|
||||
.
|
||||
.
|
||||
...
|
||||
</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:
|
||||
@@ -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:
|
||||
<code>
|
||||
fluffy, twinkie: CAT
|
||||
.
|
||||
.
|
||||
...
|
||||
my_cats.put (fluffy)
|
||||
my_cats.put (twinkie)
|
||||
</code>
|
||||
@@ -54,8 +50,8 @@ One problem with this type of list is that the type system will not help you kee
|
||||
<code>
|
||||
fluffy, twinkie: CAT
|
||||
thor: PSYCHOTIC_HYDROPHOBIC_CAT_HATING_DOG
|
||||
.
|
||||
.
|
||||
-- A very nasty dog
|
||||
...
|
||||
my_cats.put (fluffy)
|
||||
my_cats.put (twinkie)
|
||||
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]] .
|
||||
<code>
|
||||
some_cat: CAT
|
||||
.
|
||||
.
|
||||
...
|
||||
some_cat ?= my_cats.item
|
||||
if some_cat /= Void then
|
||||
some_cat.purr
|
||||
@@ -89,17 +84,15 @@ In Eiffel this is accomplished through generic classes. Generic classes are writ
|
||||
<code>
|
||||
class
|
||||
LIST [G]
|
||||
.
|
||||
.
|
||||
...
|
||||
feature -- Access
|
||||
item: G
|
||||
-- The item currently pointed to by cursor
|
||||
.
|
||||
...
|
||||
feature -- Element change
|
||||
put (new_item: G)
|
||||
-- Add `new_item' at the end of the list
|
||||
.
|
||||
.
|
||||
...
|
||||
</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]
|
||||
-- A list of my cats
|
||||
fluffy, twinkie: CAT
|
||||
.
|
||||
.
|
||||
...
|
||||
my_cats.put (fluffy)
|
||||
my_cats.put (twinkie)
|
||||
.
|
||||
...
|
||||
my_cats.item.purr -- Valid now
|
||||
</code>
|
||||
|
||||
@@ -121,10 +113,7 @@ The following would no longer be valid:
|
||||
-- A list of my cats
|
||||
|
||||
thor: PSYCHOTIC_HYDROPHOBIC_CAT_HATING_DOG
|
||||
|
||||
.
|
||||
.
|
||||
|
||||
...
|
||||
my_cats.put (thor) -- Is invalid
|
||||
</code>
|
||||
|
||||
|
||||
@@ -30,30 +30,30 @@ deferred class
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
infix "<" (other: like Current): BOOLEAN is
|
||||
infix "<" (other: like Current): BOOLEAN
|
||||
-- Is current object less than `other'?
|
||||
deferred
|
||||
end
|
||||
|
||||
infix "<=" (other: like Current): BOOLEAN is
|
||||
infix "<=" (other: like Current): BOOLEAN
|
||||
-- Is current object less than or equal to `other'?
|
||||
do
|
||||
Result := not (other < Current)
|
||||
end
|
||||
|
||||
infix ">" (other: like Current): BOOLEAN is
|
||||
infix ">" (other: like Current): BOOLEAN
|
||||
-- Is current object greater than `other'?
|
||||
do
|
||||
Result := other < Current
|
||||
end
|
||||
|
||||
infix ">=" (other: like Current): BOOLEAN is
|
||||
infix ">=" (other: like Current): BOOLEAN
|
||||
-- Is current object greater than or equal to `other'?
|
||||
do
|
||||
Result := not (Current < other)
|
||||
end
|
||||
|
||||
is_equal (other: like Current): BOOLEAN is
|
||||
is_equal (other: like Current): BOOLEAN
|
||||
-- Is `other' attached to an object of the same type
|
||||
-- as current object and identical to it?
|
||||
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.
|
||||
<code>
|
||||
class RECTANGLE
|
||||
class
|
||||
RECTANGLE
|
||||
inherit
|
||||
POLYGON
|
||||
redefine
|
||||
@@ -279,7 +280,7 @@ inherit
|
||||
.
|
||||
.
|
||||
feature
|
||||
perimeter: REAL is
|
||||
perimeter: REAL
|
||||
-- Sum of lengths of all sides
|
||||
do
|
||||
Result := 2 * (width + height)
|
||||
|
||||
Reference in New Issue
Block a user