Universal class and its features

    Contents
    1. The structure of universal classes
    2. Using the universal classes
    3. Input and output features
    4. Copy and comparison routines
    5. Type information
    6. Miscellaneous

The Eiffel inheritance mechanism is set up in such a way that every class is a descendant of a Kernel Library class called ANY . The features of this class provide a number of generally applicable facilities covering such needs as comparison, copying and rudimentary input and output.

The structure of universal classes

Every class which has no inheritance clause is understood to have an inheritance clause of the form inherit ANY

As a result, every developer-defined class is a descendant of ANY . You may introduce your own project specific features in ANY so that all the classes of your system will be able to use these features.

Using the universal classes

If you need to rename or redefine a feature inherited from one of the universal classes, you should include an explicit inheritance clause, as in class C inherit ANY rename out as basic_out redefine print end ... feature ... end

The features of ANY are usable in both qualified and unqualified form. For example, the argumentless function out, which produces a printable representation of any object, may be called under either of the forms x := out x := a.out

The first call yields a printable representation of the current object; the second, which assumes that a is not void, yields a printable representation of the object attached to a.

Input and output features

Some of the features of ANY cover common input and output needs.

Feature io, of type STD_FILES , gives access to standard input and output facilities. For example, io.input is the standard input file and io.new_line will print a line feed on the standard output. Feature io is declared as a once function which, when first called, returns the value of an instance of STD_FILES that provides access to the standard input, the standard output and the error output. As a result, io is never void, so that operations such as io.new_line are always possible.

Function out, of type STRING , is a universal mechanism for obtaining a simple external representation of any object. For non-void x of any type, the string x.out is a printable representation of x. This works for x of all types, reference or expanded. For example, if x is an integer expression, x.out is its string representation, such as -897; if n is a non-void reference, x.out is (recursively) the concatenation of the result of applying out to the successive fields of the attached object, each labeled by the name of the corresponding attribute. You may redefine out in any class to specify any suitable format for displaying instances of the class. To obtain the default representation regardless of any redefinition of out, use tagged_out, declared as a frozen synonym of the original out.

The call print (x) will output the value of x.out on the default output if x is not void, and do nothing otherwise.

Copy and comparison routines

Procedure copy copies the fields of an object onto those of another. It is used under the form target.copy (source)

Here both target and source must be non-void; this means that copy is only good for copying onto an object that already exists. If you need both to allocate a new object and to initialize it as a copy of another, use the function twin. For non-void source, the assignment target := source.twin starts by creating a new object, then populates its fields to be identical to source.

The boolean function equal compares two objects for field-by-field equality. This is different from the equality operators = and /= which, in the case of reference types, compare references, not objects.

The function deep_twin produces a duplicate of an entire object structure. The boolean function deep_equal determines whether two object structures are recursively identical. These routines are the deep counterparts of the shallow copy and equality tests provided by twin and equal.

A class that needs a specific notion of equality and the corresponding copy semantics may redefine copy and is_equal (from which equal follows, since equal (a, b) is defined as a.is_equal (b) for non-void a). You will find such redefinitions in a number of classes of the Base libraries. For example an instance of STRING is a string descriptor containing a reference to the actual character sequence, not that sequence itself, so that what the default equal compares and the default copy copies is the descriptor, not the string. Class STRING redefines these routines to yield the semantics normally expected by string clients; the frozen variants standard_copy and standard_equal, originally declared as synonyms to equal and copy, remain available with the default semantics.

The function twin is defined in terms of copy, and so will follow any redefinition of copy. This makes it impossible to change the semantics of one but not of the other, which would be a mistake. The variant standard_twin is defined in terms of standard_copy.

Note: In some existing Eiffel code you may encounter the use of a function clone which is used to do the job of twin, but has a form like copy, as in target.clone (source). clone is an obsolete function. Use twin instead.

Type information

The string-valued query generator, applied to any object, returns the name of the object's generating class: the class of which it is an instance. The boolean function conforms_to makes it possible to test dynamically whether the type of an object conforms to that of another - that is to say whether the first one's generator is a descendant of the second one's.

These two features enable clients to ascertain the dynamic type of an entity at runtime. They are only useful for low-level components; the normal mechanism for type-dependent operations is dynamic binding.

Miscellaneous

The query Void, of type NONE, denotes a reference that is always void - not attached to any object.

Procedure do_nothing does what its name implies.

Function default also has an empty body; its result type is like Current, so what it returns is the default value of the current type. This is mostly interesting for expanded types, since for reference types the default value is simply a void reference.

419E822A-646B-4817-810C-B30F973A2D70