CS 228 meeting -*- Outline -*-
* design of ADT operations (HR 9.2)
** overview (p. 390)
------------------------------------------
OVERVIEW OF ADT DESIGN PROCESS
Steps involved:
1. describe (model) the abstract values
2. select and specify the operations
3. evaluate for completeness, simplicity
------------------------------------------
completeness means you can do essentially anything useful,
perhaps by programming
simplicity means it's easy to understand
** examples
*** immutable Ratl type
------------------------------------------
DESIGN OF RATIONAL NUMBER TYPES
Ratl
1. model is ___________________________
2. operations
class Ratl {
public:
Ratl(int n, int d);
// PRE: d != 0
// MODIFIES: self
// POST: self = (n/d)
int numr() const;
// POST: FCTVAL == numerator of self
int denr() const;
// POST: FCTVAL == denominator of self
#include "Ratl.pri"
};
------------------------------------------
... mathematical fractions
with numerator and denominator
Q: What is being hidden by this type?
the ability to mutate
The objects of such a type are ...
------------------------------------------
def: a ADT has *immutable objects* iff
the abstract value of the object
------------------------------------------
... can't be changed once the object is created.
Often useful for mathematical, or atomic ideas (numbers);
unusual for ADTs that are collections.
Q: Is Ratl simple?
Q: Is Ratl complete?
Q: What kinds of things might we want to do?
(make a list)
I/O
algebraic, more generally:
construction of new based on old (+, -, *, ...)
observations ( ==, !=, <, etc.)
Q: Can you program these as a client of Ratl?
if yes, then it's complete, so it's complete
Note that nothing prevents the constructor from simplifying
the fraction.
Q: What if we didn't have the denr function, would it be complete?
if didn't have both numr and denr,
then all objects would look the same to clients
*** immutable Fraction type (more operations)
Tradeoff between simplicity and utility:
the client has to write more with Ratl
------------------------------------------
A "FULL-FEATURED" TYPE DESIGN
class Fraction {
public:
// C++ constructors (primitive)
Fraction();
Fraction(int i);
Fraction(int n, int d);
// ADT-constructors (non-primitive)
Fraction operator +(Fraction oth) const;
Fraction operator -(Fraction oth) const;
// etc.
// observers
int numr() const;
int denr() const;
double DoubleEquiv() const;
Boolean operator ==(Fraction oth) const;
Boolean operator < (Fraction oth) const;
// etc.
#include "Fraction.pri"
};
ostream& operator << (ostream& out,
Fraction f);
------------------------------------------
compare to FracType in book, this one is still immutable
*** set types
------------------------------------------
MUTABLE OBJECTS
def: a ADT has *mutable objects* iff
the abstract value of the objects
------------------------------------------
... can be changed over time by the operations
------------------------------------------
KINDS OF OPERATIONS
FOR TYPES WITH MUTABLE OBJECTS
- C++ constructors (primitive)
- a C++ destructor
- ADT-constructors (non-primitive)
- observers
- mutators
e.g., Delete from an IntSet
operator =
------------------------------------------
non-primitive constructors are somewhat rarer for mutable objects
mutators important
Note, the HR book lumps together mutators and ADT-constructors,
I think that's confusing
The HR book splits (p. 394) observers into:
type conversion functions
test operations
including finiteness ops (IsFull)
selector operations (get part of the value)
It also makes a special case for assignment and copy operations
Should also note I/O, even though it's outside of a class itself
Q: Where does the assignment operator fit in? The copy constructor?
------------------------------------------
FOR YOU TO DO
(In groups of 3 or 4)
A first step in the design of an ADT
for sets of Integers.
Use mathematical sets as the model.
List operations in two parts:
(a) a minimal, but complete set
(b) others for a "full-featured" set
Also, write down any functions that
(c) should be implemented as client code.
Write down both a name and a prototype
for each operation and function.
------------------------------------------
Say not to be limited by what's in the book
Then make a list of these on the board
An example for (c) is adding the element 1 to a set.
This will give the opportunity to talk about completeness for
types with mutable objects like this
A problem with Set as specified in the book, is that there's
no way to get at the elements.
If time, specify some of these
** completeness (HR pp. 394-5)
this should be thought of as a design heuristic, not as a rule
there will be exceptions...
------------------------------------------
COMPLETENESS FOR ADTS
def: Let T be an ADT with domain D.
The design of T is *complete* iff:
1. For each abstract value v in D,
a client can construct an object
with abstract value v.
2. A client can program any computable
function on
------------------------------------------
... the abstract values.
this means you can extract all the information in the value.
------------------------------------------
3. If T has mutators,
then
------------------------------------------
... a client can modify
any given object of type T to have
any given abstract value.
Draw picture:
client capabilities
=======ADT barrier=========
representation capabilities
One way to think of this is that generally don't want to hide
the computational power of the rep,
instead the idea is to make it more convenient for the client
Counterexamples to (1):
set without any way to make an empty set
(no Delete operation, no default constructor)
Q: Does set have enough constructors?
but how do you make the set {3,4,5}?
Counterexamples to (2):
IntSet without any way to test for existence of elements
Almost a counterexample to (2), and one in practice:
IntSet without any way to get a random element and delete it.
def: an ADT design is effectively complete if any computable function
can be programmed, even if the domain is assumed infinite.
Counterexamples to (3):
suppose you could only insert elements, but not delete them
Caveat, sometimes you don't want ADTs to be complete in this sense
(esp. for property 3), but usually you do.
Sometimes the domain D is taken to be larger than needed,
just to make the task of specification easier
(e.g., allow infinite sets, or arbitrarily large integers)
------------------------------------------
TESTABILITY
def: an ADT has testable preconditions
if the veracity of each precondition
in its specifiction
------------------------------------------
... can be decided by a client program, for each object of the type.
Caveats: sometimes, it's just as easy to make a condition happen
as to provide a way to test for it
e.g., Simplify in the HR book's FracType
This is why I don't specify that a parameter is "assigned",
as it can't be tested (HR say it doesn't need to be...)