[[Property:modification_date|Thu, 02 Jul 2020 10:00:15 GMT]] [[Property:publication_date|Tue, 10 Sep 2019 23:07:44 GMT]] [[Property:title|ET: Other Mechanisms]] [[Property:weight|-4]] [[Property:uuid|c0a01664-194c-4e84-0517-8e7c1ca61dec]] We now examine a few important mechanisms that complement the preceding picture. ==Manifest constants== Sometimes we want to provide in software text a self-denoting value of a particular type. In Eiffel this is what we call a '''manifest constant'''. For example, if we are searching an indexed structure, we might have an integer variable that we would want to initialize to reference the first item in the structure: <code> my_index := 1 </code> In this case we used a manifest constant, <code>1</code>, to provide an initial value for <code>my_index</code>. In particular, this is a manifest integer. Eiffel also supports [[Eiffel_programming_language_syntax#Manifest_constants|manifest constants]] for real (and double) numbers (ex: <code>3.1415</code>), boolean values (ex: <code>True</code>, <code>False</code>), and characters (ex: <code>'A'</code>, with [[Eiffel programming language syntax#Special characters|special characters]] expressed using a percent sign as in <code>'%N'</code> for new line, <code>'%B'</code> for backspace, <code>'%"'</code> for double quote, and <code>'%U'</code> for null). Manifest constants are also available for strings, using double quotes as in: <code>"Hello world!"</code>. As with character constants, special characters are denoted using the <code>%</code> codes. ===Verbatim strings=== You may occasionally have a need for a manifest string that represents a multi-line formatted string. In Eiffel we call this type of manifest string a '''verbatim string''', and there is a special syntax for specifying verbatim strings in Eiffel code. Verbatim strings are either '''aligned''' or '''non-aligned'''. Aligned verbatim strings will automatically be adjusted so that their leftmost line (the line with text characters closest to the left margin) contains no "white space" to the left of the first text character. For non-aligned verbatim strings, the white space is left untouched. You use a slightly different way of specifying each type of string. For example, this aligned verbatim string: <code> my_aligned_string: STRING = "[ Thrice hail the still unconquered King of Song! For all adore and love the Master Art That reareth his throne in temple of the heart; And smiteth chords of passion full and strong Till music sweet allures the sorrowing throng! ]" </code> will print like this: <code lang="text"> Thrice hail the still unconquered King of Song! For all adore and love the Master Art That reareth his throne in temple of the heart; And smiteth chords of passion full and strong Till music sweet allures the sorrowing throng! </code> The same string, declared as a non-aligned verbatim string: <code> my_non_aligned_string: STRING = "{ Thrice hail the still unconquered King of Song! For all adore and love the Master Art That reareth his throne in temple of the heart; And smiteth chords of passion full and strong Till music sweet allures the sorrowing throng! }" </code> will print like this: <code lang="text"> Thrice hail the still unconquered King of Song! For all adore and love the Master Art That reareth his throne in temple of the heart; And smiteth chords of passion full and strong Till music sweet allures the sorrowing throng! </code> The difference in declaration is that the aligned verbatim string uses as its "opener" the double-quote plus bracket combination, " <code>"[</code> ", and the bracket plus double quote, " <code>]"</code> ", as its "closer". The non-aligned verbatim string uses braces, " <code>{</code> " and " <code>}</code> " instead of the bracket. The syntax for specifying verbatim strings allows an option for the situation in which the specified string might conflict with the "closer". You can include a simple string between the double quote and the bracket on each end of the verbatim string to guarantee uniqueness. Here's our aligned verbatim string with the simple string " <code>*?</code> " inserted in the opener and closer: <code> my_aligned_string: STRING = "*?[ Thrice hail the still unconquered King of Song! For all adore and love the Master Art That reareth his throne in temple of the heart; And smiteth chords of passion full and strong Till music sweet allures the sorrowing throng! ]*?" </code> ==Constant attributes== The attributes studied earlier were variable: each represents a field present in each instance of the class and changeable by its routines. It is also possible to declare '''constant attributes''', as in <code> Solar_system_planet_count: INTEGER = 8 </code> These will have the same value for every instance and hence do not need to occupy any space in objects at execution time. (In other approaches similar needs would be addressed by symbolic constants, as in Pascal or Ada, or macros, as in C.) What comes after the <code>=</code> is a manifest constant. So you can declare a constant attribute for any type for which there is a manifest constant. ==Obsolete features and classes== One of the conditions for producing truly great reusable software is to recognize that although you should try to get everything right the first time around you won't always succeed. But if "good enough" may be good enough for application software, it's not good enough, in the long term, for reusable software. The aim is to get ever closer to the asymptote of perfection. If you find a better way, you must implement it. The activity of generalization, discussed as part of the lifecycle, doesn't stop at the first release of a reusable library. This raises the issue of backward compatibility: how to move forward with a better design, without compromising existing applications that used the previous version? The notion of obsolete class and feature helps address this issue. By declaring a feature as <code>obsolete</code>, using the syntax <code> enter (i: INTEGER; x: G) obsolete "Use ` put (x, i)' instead " require ... do put (x, i) end </code> you state that you are now advising against using it, and suggest a replacement through the message that follows the keyword <code>obsolete</code>, a mere string. The obsolete feature is still there, however; using it will cause no other harm than a warning message when someone compiles a system that includes a call to it. Indeed, you don't want to hold a gun to your client authors' forehead (''"Upgrade now or die !"''); but you do want to let them know that there is a new version and that they should upgrade at their leisure. Besides routines, you may also mark classes as obsolete. The example above is a historical one, involving an early change of interface for the EiffelBase library class <code>ARRAY</code>; the change affected both the feature's name, with a new name ensuring better consistency with other classes, and the order of arguments, again for consistency. It shows the recommended style for using <code>obsolete</code>: <br/> * In the message following the keyword, explain the recommended replacement. This message will be part of the warning produced by the compiler for a system that includes the obsolete element. * In the body of the routine, it is usually appropriate, as here, to replace the original implementation by a call to the new version. This may imply a small performance overhead, but simplifies maintenance and avoids errors. It is good discipline not to let obsolete elements linger around for too long. The next major new release, after a suitable grace period, should remove them. The design flexibility afforded by the <code>obsolete</code> keyword is critical to ensure the harmonious long-term development of ambitious reusable software. ==Creation variants== The basic forms of creation instruction, and the one most commonly used, are the two illustrated earlier ( [[ET: The Dynamic Structure: Execution Model#Creating_and_initializing_objects|"Creating and initializing objects"]] ): <code> create x.make (2000) create x </code> the first one if the corresponding class has a <code>create</code> clause, the second one if not. In either form you may include a type name in braces, as in <code> create {SAVINGS_ACCOUNT} x.make (2000) </code> which is valid only if the type listed, here <code>SAVINGS_ACCOUNT</code>, conforms to the type of <code>x</code>, assumed here to be <code>ACCOUNT</code>. This avoids introducing a local entity, as in <code> local xs: SAVINGS_ACCOUNT do create xs.make (2000) x := xs ... </code> and has exactly the same effect. Another variant is the '''creation expression''', which always lists the type, but returns a value instead of being an instruction. It is useful in the following context: <code> some_routine (create {ACCOUNT}.make (2000)) </code> which you may again view as an abbreviation for a more verbose form that would need a local entity, using a creation instruction: <code> local x: ACCOUNT do create x.make (2000) some_routine (x) ... </code> Unlike creation instructions, creation expressions must always list the type explicitly, <code>{ACCOUNT}</code> in the example. They are useful in the case shown: creating an object that only serves as an argument to be passed to a routine. If you need to retain access to the object through an entity, the instruction <code>create x</code> ... is the appropriate construct. The creation mechanism gets an extra degree of flexibility through the notion of <code>default_create</code>. The simplest form of creation instruction, <code>create x</code> without an explicit creation procedure, is actually an abbreviation for <code>create x.default_create</code>, where <code>default_create</code> is a procedure defined in class <code>ANY</code> to do nothing. By redefining <code>default_create</code> in one of your classes, you can ensure that <code>create x</code> will take care of non-default initialization (and ensure the invariant if needed). When a class has no <code>create</code> clause, it's considered to have one that lists only <code>default_create</code>. If you want to allow <code>create x</code> as well as the use of some explicit creation procedures, simply list <code>default_create</code> along with these procedures in the <code>create</code> clause. To disallow creation altogether, include an empty <code>create</code> clause, although this technique is seldom needed since most non-creatable classes are deferred, and one can't instantiate a deferred class. One final twist is the mechanism for creating instances of formal generic parameters. For <code>x</code> of type <code>G</code> in a class <code>C [G]</code>, it wouldn't be safe to allow <code>create x</code>, since <code>G</code> stands for many possible types, all of which may have their own creation procedures. To allow such creation instructions, we rely on constrained genericity. You may declare a class as <code> [G -> T create cp end] </code> to make <code>G</code> constrained by <code>T</code>, as we learned before, and specify that any actual generic parameter must have <code>cp</code> among its creation procedures. Then it's permitted to use <code>create x.cp</code>, with arguments if required by <code>cp</code>, since it is guaranteed to be safe. The mechanism is very general since you may use <code>ANY</code> for <code>T</code> and <code>default_create</code> for <code>cp</code>. The only requirement on <code>cp</code> is that it must be a procedure of <code>T</code>, not necessarily a creation procedure; this permits using the mechanism even if <code>T</code> is deferred, a common occurrence. It's only descendants of <code>T</code> that must make <code>cp</code> a creation procedure, by listing it in the <code>create</code> clause, if they want to serve as actual generic parameters for <code>C</code>. ==Non-object calls== The Eiffel model for object-oriented computation involves the application of some feature <code>f</code> to some object <code>x</code>, and possibly passing arguments <code>a</code>: <code> x.f (a) </code> This type of feature call is known as an '''object call''' because it applies the feature to a target object, in this case <code>x</code>. However, under certain circumstances we may apply a feature of a class in a fashion that does not involve a target object. This type of call is a '''non-object call'''. In place of the target object, the syntax of the non-object call uses the type on which the feature can be found. <code> circumference := radius * 2.0 * {MATH_CONST}.pi </code> In the sample above, the call to feature <code>{MATH_CONST}.Pi</code> is a non-object call. This case illustrates one of the primary uses of non-object calls: constants. The library class <code>MATH_CONST</code> contains commonly used mathematical constants. Non-object calls make it possible to use the constants in <code>MATH_CONST</code> without having to create an instance of <code>MATH_CONST</code> or inherit from it. The other primary use is for external features. One example is when we use Microsoft .NET classes from Eiffel code and have to access mechanisms for which there is no direct analog in Eiffel. Microsoft .NET supports so-called "static" methods and enumeration types. To access these, we use non-object calls. In the example below, a non-object call is used to access the enumeration <code lang="text">CreateNew</code> from the .NET enumeration type <code lang="text">System.IO.FileMode</code>. <code> create my_file_stream.make ("my_file.txt", {FILE_MODE}.create_new) </code> The validity of a non-object call is restricted in ways that mirror these primary uses. That is, any feature called in a non-object call must be either a constant attribute, an external feature, or a class feature. (See the [[ECMA Standard 367|ISO/ECMA Eiffel standard document]] for additional details.) === Class feature === A feature with a class postcondition is known as a class feature and can be used in non-object calls. A class postcondition consists of a single keyword <code lang="eiffel">class</code> (with an optional leading tag): <code> disc_area (radius: REAL_32): REAL_32 -- Area of a disk of radius `radius`. do Result := radius * radius * {MATH_CONST}.pi ensure instance_free: class end </code> A class feature can be used not only in object calls, but also in non-object calls. For example, assuming the feature above is defined in class <code lang="eiffel">GEOMETRY</code>, it can be called without creating an object: <code> area := {GEOMETRY}.disc_area (r) </code> A class feature is valid only when it does not * access <code lang="eiffel">Current</code>; * access a variable attribute; * declare an unqualified agent; * make an unqualified call to a non-class feature. Although an external feature without assertions can be used in non-object calls, it is a good practice to add a class postcondition if such usage is expected. This guarantees that no added or inherited assertion violates the validity rule for a class feature. ==Convertibility== It is useful at times to designate that instances of one type can be created through the controlled conversion of instances of some other type. This can be done through a safe Eiffel type conversion mechanism called '''convertibility'''. Convertibility is useful when refactoring, moving from one design to another, or, as you will see in the example, accommodating external technologies over which we have no control. {{Definition|Convertibility: converts to, converts from|<br/> <br/> A type U based on a class CU '''converts to''' a type T based on a class CT (and T '''converts from''' U) if either<br/> <br/> CT has a ''conversion procedure'' using U as a conversion type, or <br/> <br/> CU has a ''conversion query'' listing T as a conversion type,<br/> <br/> but not both.}} Before we get into an example of convertibility, let's list some of its underlying principles: # Conversion Principle: No type may both ''conform'' and ''convert'' to another. # Conversion Asymmetry Principle: No type may convert to another through both a ''conversion procedure'' and a ''conversion query''. # Conversion Non-transitivity Principle: That V converts to U and U converts to T does not imply that V converts to T. Let's look at an example with which you may already be familiar. <code> my_string: STRING_8 -- Native Eiffel string my_system_string: SYSTEM_STRING -- Native Microsoft .Net string … my_string := my_system_string </code> In the snippet above, we have attributes declared of type <code>STRING_8</code> and <code>SYSTEM_STRING</code>. We know that if we have a attribute of type <code>STRING_8</code> that we can make a direct assignment of a .Net type of string (that is, the .Net type <code>System.String</code> which we see as class <code>SYSTEM_STRING</code>) to our <code>STRING_8</code> attribute. We know also that <code>SYSTEM_STRING</code> does not conform to <code>STRING_8</code>, so according to the definition of [[ET: Instructions#Assignment and attachment|compatibility]], this must happen through conversion. Therefore <code>SYSTEM_STRING</code> converts to <code>STRING_8</code>. And according to the definition above this means that either: # Class <code>SYSTEM_STRING</code> has a conversion query listing <code>STRING_8</code> as a conversion type, or # Class <code>STRING_8</code> has a conversion procedure listing <code>SYSTEM_STRING</code> as a conversion type In this case <code>STRING_8</code> has a conversion procedure for objects of type <code>SYSTEM_STRING</code>. Conversion procedures are always [[ET: The Dynamic Structure: Execution Model#Creating and initializing objects|creation procedures]]. So they appear in both the <code>create</code> and the <code>convert</code> parts of the class. <code> class STRING_8 … create make_from_cil … convert make_from_cil ({SYSTEM_STRING}) … </code> We won't show the implementation of the conversion procedure, but as you can imagine, it initializes its target with the content of its argument. Because of convertibility, this code: <code> my_string := my_system_string </code> is equivalent to: <code> create my_string.make_from_cil (my_system_string) </code> So, we've seen how <code>SYSTEM_STRING</code> converts to <code>STRING_8</code>. But, in the context of our example, we could also do this: <code> my_system_string := my_string </code> Which means that <code>STRING_8</code> converts to <code>SYSTEM_STRING</code>. The <code>convert</code> part of class <code>STRING_8</code> also has a conversion query listing <code>SYSTEM_STRING</code> as a conversion type: <code> class STRING_8 … create make_from_cil … convert make_from_cil ({SYSTEM_STRING}) to_cil: {SYSTEM_STRING} … </code> Because of convertibility, this code: <code> my_system_string := my_string </code> is equivalent to: <code> my_system_string := my_string.to_cil </code> You should bear in mind that assignments are not the only situation in which conversions take place. Convertibility works for other types of attachments as well. For example, if a routine calls for an argument of type <code>SYSTEM_STRING</code>, and you supply an actual argument of type <code>STRING_8</code>, this constitutes an attachment, and the conversion from <code>STRING</code> to <code>SYSTEM_STRING</code> will occur. ==Tuple types== The study of genericity described arrays. Another common kind of container objects bears some resemblance to arrays: sequences, or "tuples", of elements of specified types. The difference is that all elements of an array were of the same type, or a conforming one, whereas for tuples you will specify the types we want for each relevant element. A typical tuple type is of the form <code> TUPLE [X, Y, Z] </code> denoting a tuple of at least three elements, such that the type of the first conforms to <code>X</code>, the second to <code>Y</code>, and the third to <code>Z</code>. You may list any number of types in brackets, including none at all: <code>TUPLE</code>, with no types in brackets, denotes tuples of arbitrary length. {{info|The syntax, with brackets, is intentionally reminiscent of generic classes, but <code>TUPLE</code> is a reserved word, not the name of a class; making it a class would not work since a generic class has a fixed number of generic parameters. You may indeed use <code>TUPLE</code> to obtain the effect of a generic class with a variable number of parameters. }} To write the tuples themselves -- the sequences of elements, instances of a tuple type -- you will also use square brackets; for example <code> [x1, y1, z1] </code> with <code>x1</code> of type <code>X</code> and so on is a tuple of type <code>TUPLE [X, Y, Z]</code>. The definition of tuple types states that <code>TUPLE [X1 ... Xn]</code> denotes sequences of at least <code>n</code> elements, of which the first <code>n</code> have types respectively conforming to <code>X1, ..., Xn</code>. Such a sequence may have more than <code>n</code> elements. Features available on tuple types include <code>count: INTEGER</code>, yielding the number of elements in a tuple, <code>item (i: INTEGER): ANY</code> which returns the <code>i</code>-th element, and <code>put</code> which replaces an element. Tuples are appropriate when these are the only operations you need, that is to say, you are using sequences with no further structure or properties. Tuples give you "anonymous classes" with predefined features <code>count</code>, <code>item</code> and <code>put</code>. A typical example is a general-purpose output procedure that takes an arbitrary sequence of values, of arbitrary types, and prints them. It may simply take an argument of type <code>TUPLE</code>, so that clients can call it under the form <code> write ([your_integer, your_real, your_account]) </code> As soon as you need a type with more specific features, you should define a class.