A RAC is a container for data that supports at most only two behaviors: add (an element) and remove (an element) and whose internal storage implementations are not visible to its users.
remove is not required to remove the element put in by the latest add!
A RAC is thus either
-- EmptyRAC, with only the add behavior
-- NERAC (non-empty RAC), with both the add and remove behaviors. first is the element that is eliminated from the RAC by remove.
At this level, the behaviors of add and remove are not specified, just that they will somehow add and remove elements. We say that add and remove are abstract behaviors.
Thus, we say that a RAC, as well as EmptyRAC and NERAC, are abstract classes since they represents the abstract behaviors of a whole family of possibilities.
However, the empty/non-empty structure of a RAC leads to the ability to write a RACVisitor and an attendent racExecute. Any visitor to a RAC would be restricted to using the RAC's add, remove and first behaviors without knowing what they actually did, only that they moved data in and out of the RAC.
We can thus see that RACVisitors run at a very high abstraction level.
So if a RAC is abstract, it cannot be instantiated directly because its behaviors aren't defined. So what's a real, concrete RAC? In other words, what would be an example of a concrete sub-class of RAC, which does have well defined adding and removing behavior?
Stack: First In/ Last Out (FILO) or Last In/First Out (LIFO) -- remove eliminates the element put in with the most recent add.
Queue: First In/First Out (FIFO) -- remove eliminates the element put in with the least recent add
Priority Queue: remove eliminates the element identified by some assessment of all the data stored in the RAC. Example: First In/Biggest Out.
How do we get those two functions to work on the same, yet private-to-each-RAC data store?
(Did we just talk about this?)
©2003 Stephen Wong