Adding new observers
OOP
template< class E >
int length(list< E >* l) { length
return l->empty() ? 0 : 1 + length( l->tail() );
}
template< class E >
class listWL : public list<E> { listWL
public:
int length() { return ::length( this ); }
};
slide: Objects and observers
A program fragment illustrating the use of the
listWL class is given below.
list<int>* r = new cons<int>(1,new cons<int>(2,new interval(3,7)));
while (! r->empty()) {
cout << ((listWL< int >*)r)->length() << endl;
r = r->tail();
}
delete r;
Evidently, we need to
employ a cast whenever we wish to
apply the length observer function.
Hence, this seems not to be the right solution.
Alternatively, we may use the function length directly.
However, we are then forced to mix method
syntax of the form with function syntax
of the form , which may easily lead
to confusion.
Discussion
We may wonder why an object-oriented approach,
that is supposed to support extensibility, is
at a disadvantage here when compared to a more
traditional module-based approach.
As observed in [Cook90], the problem lies in the fact
that neither of the two approaches reflect
the full potential and flexibility of
the matrix specification of an abstract data type.
Each of the approaches represents a particular choice
with respect to the decomposition of the matrix, into
either an operations-oriented (horizontal) decomposition
or a data-oriented (vertical) decomposition.
The apparent misbehavior of an object realization
with respect to extending the specification with observer
functions explains why in some cases we prefer
the use of overloaded functions rather than methods,
since overloaded functions allow for implicit dispatching
to take place on multiple arguments,
whereas method dispatching behavior is determined only
by the type of the object.
However, it must be noted that the dispatching behavior
of overloaded functions in C++ is of a purely syntactic nature.
This means that we cannot exploit the information
specific for a class type as we can when using
virtual functions.
Hence, to employ this information we would be required
to write as many variants of overloaded functions
as there are combinations of argument
types.
Dynamic dispatching on multiple arguments is
supported by
multi-methods in CLOS,
see [Paepcke93].
According to [Cook90], the need for such methods
might be taken as a hint that objects
only partially realize the true potential of data abstraction.
(C) Æliens
04/09/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.