[comp.lang.eiffel] a problem in programming with Eiffel

gt0460d@prism.gatech.EDU (DSOUZA,ROSARIO JOHN) (01/22/91)

I have a curious problem. I am writing an application in Eiffel that
makes use of the graphics library. In particular, I need to use objects
that are similar to the class COMPLEX_FIG in the library, yet a little
different from it. My class is similar in the sense that it is to have
a list of figures and the whole list has to behave like a figure. But it
is different because the figures in the list are really going to be a
special type of figure that is a descendant of class FIGURE.

At first I thought that I could make my class a descendent of the class
COMPLEX_FIG and proceed from there. This is the most natural solution.
However, it turns out that COMPLEX_FIG inherits from FIG and LINKED_LIST,
and the generic parameter of the linked list is FIGURE. This causes a
problem because I need the generic parameter to be something that is 
capable of responding to feature calls of my special figure. This 
seemingly cannot be done because the generic parameter is hardwired,
so to speak, to the class FIGURE.

My question is: short of duplicating the code for COMPLEX_FIG with the
generic parameter of the inherited linked list now as my special figure,
is there any other better way to solve the problem?

I suspect that the problem is not just a matter of good library design,
but also a problem of language design. Could someone enlighten me?

..Ross D'Souza
Georgia Tech.
ross@cc.gatech.edu

nosmo@eiffel.UUCP (Vince Kraemer) (01/23/91)

The solution is simple; depending upon the use of the language feature
"association types". Association types appear as declarations in Eiffel
code as ": like <anchor-object>".  By redefining the anchor object in a
class which takes advantage of this feature, all the associated objects
are effectively redeclared.

The library classes (specifically LINKED_LIST) were written with just
such a problem in mind and allow the user to take advantage of this
technique.  By reviewing the code for linked_list, it is easy to
determine that first and first_element are the anchors for the the
routines in linked list which are originally declared as FIGURES.

The sample code to illustrate the solution to this "problem" is
appended to this message as a shar-chive file.

(Note: this code has been tested using both the 2.2B and 2.3 releases.
You will have to modify the .eiffel file to compile it under 2.2B, though)

Vince Kraemer
ISE Tech. Support
(technical correspondence to: eiffel@eiffel.com)
---------------------------------------------------------------
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by geneve!nosmo on Tue Jan 22 09:15:40 PST 1991
# Contents:  .eiffel special_c_f.e special_f.e special_test.e
 
echo x - .eiffel
sed 's/^@//' > ".eiffel" <<'@//E*O*F .eiffel//'
------------ EIFFEL SYSTEM DESCRIPTION FILE -------------------
ROOT: special_test
UNIVERSE: $EIFFEL/library/support
	$EIFFEL/library/structures
	$EIFFEL/library/graphics/figure
	$EIFFEL/library/graphics/window
EXTERNAL: $EIFFEL/files/graphiclib.a -lX11 -lm
PRECONDITIONS (y): ALL
----------------------------------------------------------------
@//E*O*F .eiffel//
chmod u=rw,g=rw,o=r .eiffel
 
echo x - special_c_f.e
sed 's/^@//' > "special_c_f.e" <<'@//E*O*F special_c_f.e//'
--|---------------------------------------------------------------
--|   Copyright (C) Interactive Software Engineering, Inc.      --
--|    270 Storke Road, Suite 7 Goleta, California 93117        --
--|                   (805) 685-1006                            --
--| All rights reserved. Duplication or distribution prohibited --
--|---------------------------------------------------------------
--| Author: Vincent Kraemer @ Interactive Software Engineering
--| Created: Tue Jan 22 07:59:21 1991

class SPECIAL_C_F export
	repeat complex_fig
inherit
	
	COMPLEX_FIG
		redefine
			first, first_element
feature

	first: SPECIAL_F is
		require
			not_empty: not empty
		do
			Result := first_element.item
		end;
	
	first_element: LINKABLE [special_f];
	
invariant

end -- class SPECIAL_C_F
@//E*O*F special_c_f.e//
chmod u=rw,g=rw,o=r special_c_f.e
 
echo x - special_f.e
sed 's/^@//' > "special_f.e" <<'@//E*O*F special_f.e//'
--|---------------------------------------------------------------
--|   Copyright (C) Interactive Software Engineering, Inc.      --
--|    270 Storke Road, Suite 7 Goleta, California 93117        --
--|                   (805) 685-1006                            --
--| All rights reserved. Duplication or distribution prohibited --
--|---------------------------------------------------------------
--| Author: Vincent Kraemer @ Interactive Software Engineering
--| Created: Tue Jan 22 08:04:34 1991

class SPECIAL_F export
	repeat FIGURE, special_call
inherit

	FIGURE
	
feature

	create is do closure.Create; end;
	
	special_call is do io.putstring ("Called special_call.\n"); end;
	
	recompute_closure is do end;

	convert_to_resolution (rv: REAL) is do end;

	origin: POINT;

	barycenter: POINT;

	duplicate: like Current is do end;

	translate (V: VECTOR) is do end;

	rotate (a: REAL; p: like origin) is do end;

	scale (f: REAL; a: like origin) is do end;

	display (w: graph_window) is do end;

	erase (w: GRAPH_WINDOW) is do end;

	contains (p: like origin): BOOLEAN is do end;

invariant

end -- class SPECIAL_F
@//E*O*F special_f.e//
chmod u=rw,g=rw,o=r special_f.e
 
echo x - special_test.e
sed 's/^@//' > "special_test.e" <<'@//E*O*F special_test.e//'
--|---------------------------------------------------------------
--|   Copyright (C) Interactive Software Engineering, Inc.      --
--|    270 Storke Road, Suite 7 Goleta, California 93117        --
--|                   (805) 685-1006                            --
--| All rights reserved. Duplication or distribution prohibited --
--|---------------------------------------------------------------
--| Author: Vincent Kraemer @ Interactive Software Engineering
--| Created: Tue Jan 22 08:13:14 1991

class SPECIAL_TEST

feature

	create is
		local
			sf: SPECIAL_F;
			scf: SPECIAL_C_F;
		do
			sf.create;
			scf.create;
			scf.put_right (sf);
			sf := scf.i_th (1);
			sf.special_call
		end;
	
end -- class SPECIAL_TEST
@//E*O*F special_test.e//
chmod u=rw,g=rw,o=r special_test.e
 
exit 0

paj@mrcu (Paul Johnson) (01/23/91)

>I have a curious problem.  I am writing an application in Eiffel that
>makes use of the graphics library. In particular, I need to use
>objects that are similar to the class COMPLEX_FIG in the library, yet
>a little different from it. My class is similar in the sense that it
>is to have a list of figures and the whole list has to behave like a
>figure. But it is different because the figures in the list are
>really going to be a special type of figure that is a descendant of
>class FIGURE.

>At first I thought that I could make my class a descendent of the class
>COMPLEX_FIG and proceed from there. This is the most natural solution.
>However, it turns out that COMPLEX_FIG inherits from FIG and LINKED_LIST,
>and the generic parameter of the linked list is FIGURE. This causes a
>problem because I need the generic parameter to be something that is 
>capable of responding to feature calls of my special figure. This 
>seemingly cannot be done because the generic parameter is hardwired,
>so to speak, to the class FIGURE.

>My question is: short of duplicating the code for COMPLEX_FIG with the
>generic parameter of the inherited linked list now as my special figure,
>is there any other better way to solve the problem?

>I suspect that the problem is not just a matter of good library design,
>but also a problem of language design. Could someone enlighten me?

I will try, although I have not checked the following against the
Eiffel type rules.  Hence it may not work.

When you produce your child of COMPLEX_FIG (say, MY_COMPLEX_FIG,
although this would be a bad name in practice) you should say
`redefine first; rename first as old_first' and then define `first' as
being of the appropriate type and returning (using the reverse
assignment operator `?=') the value of `old_first'.  All the other
features of LINKED_LIST are `like first', so this will make the change
to all of them.

This is the first time I have really appreciated the utility of `like'.

If this does not work then use the reverse assignment operator outside
of COMPLEX_FIG to undo the type loss before applying your features.

Paul.
-- 
Paul Johnson                               UUCP: <world>!mcvax!ukc!gec-mrc!paj
--------------------------------!-------------------------|-------------------
GEC-Marconi Research is not 	| Telex: 995016 GECRES G  | Tel: +44 245 73331
responsible for my opinions.	| Inet: paj@uk.co.gec-mrc | Fax: +44 245 75244