mirror of
https://github.com/EiffelSoftware/eiffel-org.git
synced 2025-12-07 15:22:31 +01:00
git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@2400 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
221 lines
14 KiB
Plaintext
221 lines
14 KiB
Plaintext
[[Property:modification_date|Mon, 25 Sep 2023 09:37:39 GMT]]
|
|
[[Property:publication_date|Mon, 25 Sep 2023 09:37:39 GMT]]
|
|
[[Property:title|Eiffel Class and Feature Names]]
|
|
[[Property:weight|2]]
|
|
[[Property:uuid|16e4a231-7aae-4b37-52fd-67876cc222ad]]
|
|
Certain naming conventions are respected by Eiffel programmers. Although Eiffel is not case-sensitive, convention dictates the use of upper and lower case in particular situations. When you program in Eiffel for .NET, you create new Eiffel classes, but you also use types from .NET assemblies. These .NET types are presented to you in a view that is consistent with Eiffel conventions.
|
|
|
|
==Eiffel Class Names==
|
|
|
|
Convention dictates that Eiffel class names are always all upper case characters with words separated by the underscore ("_") character. Eiffel classes are not qualified by "namespace" as in some other languages. This means that Eiffel class names must be unique with in a system. It also means that any types from existing .NET assemblies will have their names mapped to conventional Eiffel class names in order to be used by Eiffel classes in EiffelEnvision
|
|
|
|
Here are some class names and their descriptions from the Eiffel Base Library. These class names comply with the Eiffel class naming convention.
|
|
<code>
|
|
STRING
|
|
|
|
Sequences of characters, accessible through integer indices in a contiguous range.
|
|
|
|
RANDOM
|
|
|
|
Pseudo-random number sequence, linear congruential method.
|
|
|
|
ARRAYED_LIST
|
|
|
|
Lists implemented by resizable arrays.
|
|
|
|
LINKED_QUEUE
|
|
|
|
Unbounded queues implemented as linked lists.
|
|
|
|
</code>
|
|
|
|
Now here are some type names from the .NET mscorlib as they appear as conventional Eiffel class names (i.e. , in the form in which they become available to Eiffel for .NET programmers), followed by their full .NET type and their Summary from the .NET library. names.
|
|
<code>
|
|
SYSTEM_STRING
|
|
|
|
System.String
|
|
|
|
Represents an immutable series of characters.
|
|
|
|
SYSTEM_RANDOM
|
|
|
|
System.Random
|
|
|
|
Represents a pseudo-random number generator, a device that produces a sequence of numbers that meet certain statistical requirements for randomness.
|
|
|
|
ARRAY_LIST
|
|
|
|
System.Collections.ArrayList
|
|
|
|
Implements the System.Collections.IListinterface using an array whose size is dynamically increased as required.
|
|
|
|
SYSTEM_QUEUE
|
|
|
|
System.Collections.Queue
|
|
|
|
Represents a first-in, first-out collection of objects.
|
|
|
|
</code>
|
|
|
|
In summary, Eiffel class names and type names from .NET assemblies made available to Eiffel programmers will be all upper case, with words separated by the underscore character.
|
|
|
|
===Eiffel Names for .NET Types===
|
|
|
|
How Eiffel compliant names are derived from .NET type names is fairly simple in most cases. The "simple" class name, that is, the word following the rightmost dot in the full class name, is converted to an Eiffel compliant name by making it upper case and separating in embedded words by underscore. In the example above, <code>System.Collection.ArrayList</code> becomes <code>ARRAY_LIST</code>.
|
|
|
|
The other cases in the example are not quite so simple. If the basic derivation produces a name which conflicts with a classname in the Eiffel Base Library, then it will be disambiguated. The simple derivation of <eiffel>System.String</eiffel> would be <eiffel>STRING</eiffel>, but this would conflict with Eiffel's <eiffel>STRING</eiffel> class, so <eiffel>System.String</eiffel> becomes available to Eiffel for .NET programmers as <eiffel>SYSTEM_STRING</eiffel>.
|
|
|
|
Sometimes it is better to disambiguate an entire assembly rather than handling individual exceptions to the simple derivation. This is done by specifying a common prefix for all types in the assembly. For example, EiffelEnvision uses a prefix of " <eiffel>DATA_</eiffel>" for all classes in the .NET assembly System.Data. As a result, the type <eiffel>System.Data.Constraint</eiffel> is available in Eiffel as class <eiffel>DATA_CONSTRAINT</eiffel>.
|
|
|
|
You'll see a little more about namespaces, assemblies, and Eiffel clusters in [[Type Organization|Type Organization]] .
|
|
|
|
===Similar Types from Both Libraries===
|
|
|
|
You may have noticed a similarity in the names and descriptions from the Eiffel Base Library and those from the .NET "mscorlib" library. This is not by accident. The Eiffel class <code>STRING</code> is a different class from the .NET type <code>System.String</code>, which Eiffel programmers see represented as Eiffel class <code>SYSTEM_STRING</code>. There is more on this subject in [[Similar Types Occurring in Both Libraries|Similar Types Occurring in Both Libraries]] .
|
|
|
|
==Eiffel Feature Names==
|
|
|
|
By convention, feature names in Eiffel use all lower case characters, and like class names, words are separated by underscore. Also as with class names, the names of members from .NET assemblies will be represented in a form that complies with the Eiffel convention.
|
|
|
|
Let's look at some simple examples. First some feature names from the Eiffel Base Library.
|
|
<code>
|
|
to_upper
|
|
|
|
From class STRING: Converts to upper case.
|
|
|
|
item_double
|
|
|
|
From class RANDOM: The current random number as a double between 0 and 1
|
|
|
|
</code>
|
|
|
|
Now check out these member names from the .NET "mscorlib" type library. These have been made available to Eiffel for .NET programmers in the Eiffel convention. Following the Eiffel name, you see their .NET member name and type name.
|
|
<code>
|
|
to_upper
|
|
|
|
Member ToUpper from typeSystem.String
|
|
|
|
Returns a new System.String with the same content as the target, except all upper case.
|
|
|
|
next_double
|
|
|
|
Member NextDouble from type System.Random
|
|
|
|
A double-precision floating point number greater than or equal to 0.0, and less than 1.0.
|
|
|
|
</code>
|
|
|
|
So, Eiffel feature names, and the names of .NET members made available to Eiffel for .NET programmers, are all lower case with words separated by underscores.
|
|
|
|
==Overloaded .NET Member Names==
|
|
|
|
The .NET object model allows overloading of function names. This means that a .NET type can support multiple functions with the same name, that vary only by the types of the arguments they accept. For example, the .NET type System. Text. StringBuilder supports nineteen overloaded versions of the Append function. Here are a couple of examples, in their .NET forms:
|
|
<code>
|
|
.NET function signature: Append(System.String)
|
|
|
|
Member of type System.Text.StringBuilder
|
|
|
|
Appends a copy of the specified string to the end of this instance.
|
|
|
|
.NET function signature: Append(System.Char)
|
|
|
|
Member of type System.Text.StringBuilder
|
|
|
|
Appends the string representation of a specified Unicode character to the end of this instance.
|
|
|
|
</code>
|
|
|
|
The Eiffel programming language does not allow overloading routine names. That means that you cannot code multiple routines with the same name in a single class. That in itself is not a problem. But it also means that to work in the .NET environment, where overloading is allowed some compromise has to be made. So, what happens is this: if you are programming in Eiffel for .NET and you are using types from a .NET assembly, those types will be presented to you as if they are Eiffel classes. We have already seen that the type and feature names will be shown in the Eiffel naming convention. With overloaded feature names, the presentation will use name augmentation to disambiguate the overloaded versions. What you see is a distinct feature name for each overloaded version. The basic feature name is augmented by adding the types of its respective arguments, separated by underscore.
|
|
|
|
Let's look again at the two <code>Append</code> functions from <code>System.Text.StringBuilder</code>.
|
|
<code>
|
|
.NET function signature: Append(System.String)
|
|
|
|
Known to Eiffel as: append_string (value: SYSTEM_STRING)
|
|
|
|
Member of type System.Text.StringBuilder, known to Eiffel as STRING_BUILDER
|
|
|
|
Appends a copy of the specified string to the end of this instance.
|
|
|
|
.NET function signature: Append(System.Char)
|
|
|
|
Known to Eiffel as: append_character (value: CHARACTER)
|
|
|
|
Member of type System.Text.StringBuilder, known to Eiffel as STRING_BUILDER
|
|
|
|
Appends the string representation of a specified Unicode character to the end of this instance.
|
|
|
|
</code>
|
|
|
|
The overloading story does not end quite yet. The .NET object model allows the overloading of constructors. This issue will be discussed in the section Constructors and Creation Procedures.
|
|
|
|
==.NET Properties as Eiffel Features==
|
|
|
|
Properties in .NET provide:
|
|
* the opportunity to '''strengthen encapsulation,''' because values cannot be receive assignment without executing the property's "set" code
|
|
* '''uniform access ''' queries because properties are queries, but unlike previous C-style OO languages in which properties did not exist, if a property is used in programming a client class, the programmer does not need to know whether the data provided by the property was done so from memory or through computation. This leaves the producer of the class with the property the latitude to change the implementation without breaking existing clients.
|
|
|
|
In Eiffel, the same goals are fulfilled, but a little differently. Simple attributes are well-encapsulated, because the Eiffel programming language does not allow direct assignment to them from outside the control of their class. So any assignment of the form <code>x</code>. <code>f</code> := <code>y</code> is not valid in Eiffel. To allow client to set values of the attribute <code>f</code>, the producer of the class of which <code>x</code> is an instance would have built a command (a "<code>set_</code>" procedure) to do so. Then the code in a client to set <code>f</code> would look like this: <code>x</code>.<code>set_f</code> (<code>y</code>).
|
|
|
|
Uniform access is achieved in Eiffel through the way in which clientssee features which are queries. The code " <code>print</code> ( <code>x</code>.<code>count</code>)" applies the query <code>count</code> to the object attached to <code>x</code> and prints the result. You cannot tell by looking at this code whether <code>count</code> is an attribute or a function, that is, whether the <code>count</code> is returned from memory or through computation. In fact, it could be either, but that is a matter for its producer to deal with. As reuse consumers the implementation of <code>count</code>is not important to us ...but the fact that the producer can change the implementation without causing our code to need modification is very important to us.
|
|
|
|
Because Eiffel does not support properties directly, the propertiesof typeswhich Eiffel for .NET programmers usefrom .NET assemblies have to be mapped to Eiffel features.
|
|
|
|
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 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>
|
|
local
|
|
my_window: WINFORMS_FORM
|
|
my_string: SYSTEM_STRING
|
|
do
|
|
create my_window.make
|
|
my_window.set_text (my_window_title) -- Set Text property
|
|
my_string := my_window.text -- Query Text property
|
|
.
|
|
.
|
|
end
|
|
</code>
|
|
|
|
==Static Features in .NET==
|
|
|
|
In the .NET object model it is possible for certain members of a type to be "static". When these members are used, they are used without an instance of the class as a target. In essence, they are called on the class itself.
|
|
|
|
In Eiffel for .NET, these staticmembers will made available with feature names derivedusing the same conventions as ordinary features, but applying them will be a bit different.
|
|
|
|
There is not a concept analogous to static members in Eiffel. The model for object-oriented computation in Eiffel specifies that whenever feature application takes place, there must be an object, i.e. an instance of some class, that serves as a target.
|
|
|
|
In order to use .NET types that include static members, a special syntax has been added into Eiffel for .NET. The following example uses this syntax to call a static function:
|
|
<code>
|
|
local
|
|
my_window: WINFORMS_FORM
|
|
do
|
|
create my_window.make
|
|
my_window.set_text (my_window_title)
|
|
.
|
|
.
|
|
{WINFORMS_APPLICATION}.run_form (my_window)
|
|
end
|
|
|
|
</code>
|
|
|
|
The type <code>System.Windows.Forms.Application</code> is used here. It is available to Eiffel under the name <code>WINFORMS_APPLICATION</code>. The static member being used is <code>Run</code>, in particular the overloaded version of <code>Run</code> which takes an argument of type <code>System.Windows.Forms.Form</code>. That version is available in Eiffel under the name <code>run_form</code>.
|
|
|
|
The important thing to see here is that when you need to apply a static member, you introduce the call with the keyword <code>feature</code>. Then enclose the type name in braces and apply the feature as if it were targeted to an object. This isfairly close to the way that the call would be made in C#, where the feature name would be applied to the type name, versus a target object:
|
|
<code>
|
|
{
|
|
Form my_window;
|
|
my_window = new Form();
|
|
my_window.Text = "Hello World!";
|
|
.
|
|
.
|
|
Application.Run(my_window); // This is C#
|
|
}
|
|
</code>
|
|
|
|
|
|
|
|
|