- 19.12 (released) ...
Universal class and its features
- The structure of universal classes
- Using the universal classes
- Input and output features
- Copy and comparison routines
- Type information
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
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
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.
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.
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
Here both target and source must be non-void; this means that
twin. For non-void source, the assignment
target := source.twin
starts by creating a new object, then populates its fields to be identical to
The boolean function
/= which, in the case of reference types, compare references, not objects.
A class that needs a specific notion of equality and the corresponding copy semantics may redefine
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
The string-valued query
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.
The query Void, of type
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.