Topic: Pre and Post Chaining Woes
Author: dag@control.lth.se (Dag Bruck)
Date: 26 Oct 1994 06:55:39 GMT Raw View
>>>>> "SFC" == Steve F Cipolli (P/M) <sfc@datascope.com> writes:
SFC> ..., if one were writing a class library of GUI components, which
SFC> used overloading of virtual "event" member functions to give the
SFC> user access to a change in the objects state (ie. a menu item was
SFC> selected). Such an event in many instances requires that the
SFC> event be passed on to its base class version of the member
SFC> function (so for example the visual effect of selecting the menu
SFC> item can occur). Thus, it becomes a requirement of the user of
SFC> the class (by derivation) to ensure that the event is chained
SFC> back to its base.
I think this problem is better solved by rearranging the
responsibilities in the class hierarchy.
In the InterViews GUI system, for example, all the logic for changing
graphical representation, keeping track of cursor leaving the menu,
etc. is handled behind the scenes. The important virtual function is
called "do" which only needs to do the action of the menu item, not
pass events to base classes.
In short: separate the menu actions from the menu logic, and only
redifine the actions.
-- Dag Bruck
Author: sfc@datascope.com (Steve F. Cipolli (P/M))
Date: Mon, 31 Oct 1994 16:26:32 GMT Raw View
Dag Bruck (dag@control.lth.se) wrote:
: >>>>> "SFC" == Steve F Cipolli (P/M) <sfc@datascope.com> writes:
: SFC> ..., if one were writing a class library of GUI components, which
: SFC> used overloading of virtual "event" member functions to give the
: SFC> user access to a change in the objects state (ie. a menu item was
: SFC> selected). Such an event in many instances requires that the
: SFC> event be passed on to its base class version of the member
: SFC> function (so for example the visual effect of selecting the menu
: SFC> item can occur). Thus, it becomes a requirement of the user of
: SFC> the class (by derivation) to ensure that the event is chained
: SFC> back to its base.
: I think this problem is better solved by rearranging the
: responsibilities in the class hierarchy.
: In the InterViews GUI system, for example, all the logic for changing
: graphical representation, keeping track of cursor leaving the menu,
: etc. is handled behind the scenes. The important virtual function is
: called "do" which only needs to do the action of the menu item, not
: pass events to base classes.
: In short: separate the menu actions from the menu logic, and only
: redifine the actions.
Although I agree that this method is the only recourse, I don't believe it
represents a "better" implementation. The assumption which underlies your
approach, I believe, is that the GUI components are one, from-the-ground-up,
single-minded package of classes, and that there is a clear dividing line
between GUI components and user derived components. Also, I believe your
approach assumes that the GUI component classes can be hard-wired to avoid
using "user" level events. I find in many cases, that this dual programming
paradigm (user-level and library-level programming) is reasonable, but in many
other cases works poorly.
I think GUI component class hierarchies are one case where your assumptions
will not hold. If, for example, someone wanted to add components to
a GUI library, to be delivered to other users. The developer would either
have to understand the inner workings of the library (ie. use the
library-level events), or would have to use the user-level events as its
internal events and create new events for the user-level presented to the
final end-user. I think this delineation of user and library level
programming runs completely counter to the very nature of inheritence.
I am sure that this duality of programming is clearly documented in InterViews,
but once again, the language itself does not document such interfaces. This
is the reason why many GUI class hierarhies are so hard to use, and extend.
I, by no means are an expert on InterViews, but my understanding of it is that
it is a construction set, or "language" for the development of GUI components.
In this it is quite good, but it requires users to understand it's
"language" to use it. I would prefer class libraries to be actual mechanism,
and let C++ be the language of construction. A rather standard feature of
object-oriented languages would go a long way to making this possible.
(Responders, I do not wish to extend this topic into a debate on the merits
InterViews).
I would like to hear the arguments for and against "chaining" syntax that
have been put forth to date.
Stephen Cipolli
Datascope Corp.
Author: sfc@datascope.com (Steve F. Cipolli (P/M))
Date: Tue, 25 Oct 1994 15:40:09 GMT Raw View
When I first began using C++, I thought that its lack of a formal syntax for
describing chaining of member functions back to their base classes member
functions was a blessing. It seemed to reduce syntax headaches and provide
maximum flexibility.
I have recently begun to change my mind on this topic. Here's why, if one were
writing a class library of GUI components, which used overloading of virtual
"event" member functions to give the user access to a change in the objects
state (ie. a menu item was selected). Such an event in many instances
requires that the event be passed on to its base class version of the member
function (so for example the visual effect of selecting the menu item can
occur). Thus, it becomes a requirement of the user of the class (by
derivation) to ensure that the event is chained back to its base. This
requirement is not borne out by the syntax of C++. Thus, the user is left
to dependent on documentation (hopefully) to determine how to use the
class properly.
While I dread the inclusion of more syntax into C++, I have reservations about
not providing a simple inheritence interface to library users. As for those
who are preparing the skewers, I do not pretend to know the ramifications of
such an addition. I merely point out the dilema in hopes that some day a
suitable solution may be found.
I would think syntax like the following could be used:
class B {
.
.
.
public:
B();
virtual prechain int Event(int arg);
};
class Derived : public B {
.
.
.
public:
D();
int Event(int arg);
};
Several problems exist with this off-the-top-of-my-head implementation:
1. The int return value from B::Event can not be accessed by D::Event.
2. Multiple inheritence would prevent any special keyword representing the
return value from derived classes from being useful, since presumably the
"prechain" would cause the Event member function of all base classes to be
called. Thus, only the return value from the last bases Event function would
be accessible. Similar problems would exist for arguments passed by reference.
I am sure there are a great many more problems as well, but I am less
interested in the implementation issues, as I am in the theoretical issues.
If this topic has already been exhausted, please just mail me a short summary
and I will get on with life.
Stephen Cipolli
Datascope Corp.