[comp.lang.eiffel] Persistence in Eiffel

bertrand@eiffel.UUCP (Bertrand Meyer) (08/22/89)

From <1318@batserver.cs.uq.oz>, by gjc@batserver.cs.uq.oz (Cumming):

> In class STORABLE it appears necessary to use
> 
> 	object := object_of_same_class.retrieve("filename");
> 
> instead of
> 
> 	object.retrieve("filename");
> 
> Surely the compiler could infer the type of object_of_same_class from the
> class of object.

The problem was the following. (I am using the past tense
because this does not apply to the 2.2 release any more.)
The type of `object' is indeed known to the
compiler. However any feature call of the form

	object.anything

requires that `object' be in the created state. (Otherwise
an exception is triggered.) Hence the obligation to create
the object first, and then retrieve it.

This was unpleasant for several reasons, one of them being
that the Create procedure of the class may require arguments, and
have other effects which are not desired if the purpose is just
to retrieve a stored persistent structure.

The better solution, consistent with the principles of
object-oriented software construction, is to work as follows:

	retrieve_by_name ("filename");
	target ?= retrieved

Here `retrieve_by_name' is a procedure, not a function. Its effect
is to load the stored structure, which is then accessible through
the attribute `retrieved'.

This is indeed the 2.2 approach. Procedure `retrieve_by_name'
takes a filename as argument; there is also `retrieve_by_file'
which takes an argument of the Eiffel FILE type, and
`retrieve_by_descriptor' which takes an integer representing a
Unix file descriptor. These are procedures of class STORABLE;
`retrieved' (giving access to the last retrieved structure) is
an attribute of that class.

Why couldn't this approach be implemented before? The reason
was a typing problem. Attribute `retrieved' must be usable for
`target' of any possible class type. This implies two facilities,
not present in 2.1:

	- `retrieved' is declared of type ANY. ANY is a universal Kernel
	Library class; all programmer-defined classes are descendants of that
	class.

	- The assignment target := retrieved would not be valid, since it goes
	against the type rules (the type of the source should conform to,
	i.e. be a descendant of, the type of the target). The
	``Reverse Assignment Attempt'', written target ?= source, will
	assign to target a reference of the object
	referred to by `source', but only if the type of that object conforms
	to the declared type for `target'. Otherwise the effect is to make
	`target' a void reference. So in most cases the Reverse Assignment
	Attempt should be followed by

		if target.Void then
			... We didn't get what we expected ...
		else
			Got the object requested; proceed.
		end

NOTE: Some readers may have seen the Reverse Assignment Attempt under
a previous syntax: `target.Accept (source)'. The form target ?= source
was retained as less cumbersome and just as clear.


The above is just one way of supporting persistence in 2.2. A more
advanced technique uses the ENVIRONMENT Kernel Library class. See the
Eiffel Reference Manual for details.

-- Bertrand Meyer
bertrand@eiffel.com

newbery@Freeport.ira.uka.de (01/29/91)

I understand that in Eiffel you can store an external representation
of an object in a file if the object is of class ``storage''.

I would like to know a little more about the format of the representation.
One simple possibility for such a technique is to store a textual
representation of the object.  Is this how it is done in Eiffel?  or
is there a more sophisticated solution.  Is a representation of the
class itself saved as well or just the representation of the object
(supposedly one can load the external representation back in even using
another program as long as the class is the same).

Many thanks for information or pointers to where I might learn more about this,
Frances Newbery Paulisch (newbery@ira.uka.de)