CSci 581: Obj.-Oriented Design & Programming
Spring Semester 1999
Lecture Notes


Container Classes

This Web document was based on a set of "slides" created by the instructor for use in the Fall 1997 offering of the object-oriented design and programming course. That set was, in turn, based on a set of slides created by Timothy Budd to supplement chapter 15 of his textbook An Introduction to Object-Oriented Programming, Second Edition (Addison-Wesley, 1997).

This document has not been fully converted to be compatible with Budd's UUOOPJ and use of Java 1.2. The examples are in C++.


Strong Typing versus Containers

Strong typing useful because it helps to discover programming errors

But strong typing makes development of reusable collection (or container) classes difficult


Conventional Solution

Conventional containers closely tie the container and the element type

type
    Link = Record
        value : integer;
        nextELement : ^ Link;
    end;


Containers in Dynamic Languages


Three Solutions


Common Base Link Type


The Generic List Class

class List {
public:
        // constructor
    List() : firstElement(0) { }

        // operations
    void Add(Link * n)
        { n->next = firstElement; firstElement = n; }

    int isEmpty()
        { return firstElement == 0; }

    Link * First();
        { return firstElement; }

    void RemoveFirst();
        { Link * p = firstElement; 
          firstElement = firstElement-> next;
          delete p; }

    int  Includes(Link * n)
        { for (Link * p = firstElement; p; p = p->next)
            if (*p == *n) return 1;
          return 0; }

private:
        // data field
    Link * firstElement;
};

class Link {
public:
        // constructors
    Link () : next(0) { }
    Link (Link * n) : next(n) { }

        // operations
    virtual int operator == (Link *) = 0;

        // data field
    Link * next;
};


A Link for Double Precision Numbers

class  DoubleLink : public Link {
public:
    // data area
    double theValue;

    // constructor
    DoubleLink (double v) : theValue(v) {}

    // operations
    int operator == (Link * d)
        { return thisValue == ((DoubleLink *) d)->theValue; }
};


Using the List Class

Using the list class involves explicitly creating links.

List aList;

aList.Add(new DoubleLink(2.71828));
aList.Add(new DoubleLink(1.61803));
aList.Add(new DoubleLink(3.14159));

DoubleLink * pi;

pi = (DoubleLink *) aList.First();
aList.RemoveFirst();


Hiding the Links

Can avoid explicit manipulation of links by subclassing the List class as well.

class DoubleList : public List {
public:
    void Add(double v)
        { List::add(new DoubleLink(v)); }

    double First()
        { return firstElement->value; }

    int Includes(double v)
        { DoubleLink v1(v);
          return List::includes(v1); }
};


Containers that Hold Only Pointers


List and Link

class List {
public:
    ... // same as before

    void Add(void * v)
        { firstElement = new Link(v, firstElement); }
    
    void * First()
        { return firstElement->value; }

    ... // same as before
};

class Link {
        // constructors
    Link (void * v) : next(0), value(v) {}
    Link (void * v, Link * n) : next(n), value(v) {}

        // data areas
    Link * next;
    void * value;
};


Example: List of Windows

class WindowList : public List {
public:
    void Add(Window * w) 
        { List::add(w); }

    Window * First()
        { return (Window *) List::first(); }
};


Best Alternative: Templates


A Template List Class

template 
class List {
        // constructors
    List();

        // operations
    void Add(T v)
        { firstElement = new Link(v, firstElement); }

    int isEmpty()
        { return firstElement == 0; }

    T First()
        { return firstElement->value; }

    void RemoveFirst()
        { Link * p = firstElement;
          firstElement = p->next;
          delete p; }

    int Includes(T v)
        { for (Link * p = firstElement; p; p = p->next)
            if (v == p->value) 
                return 1;
          return 0; }
};

template 
class Link {
    // constructor
    Link (T v, Link * n) : value(v), next(n) { }

    // data fields
    Link * next;
    T value;
};


Using Template Classes

List aList;

aList.Add(2.71828);
aList.Add(1.61803);
aList.Add(3.14159);

double pi;

pi = aList.First();
aList.removeFirst();


Advantages of Templates (Generics)

Generics are available in other OOP languages such as Eiffel and Ada 95, but not in Java


Iteration and Iterators

Want mechanism for iteration over containers of values without exposing implementation

Can be performed using an iterator

In C++ can be made to look like a pointer

list::iterator start = aList.begin();
list::iterator end = aList.end();

for ( ; start != end; ++start)
    cout << (*start) << endl;


Iterator Class

template  class listIterator {
    ListIterator (Link & sl) : currentLink(sl) { }

    void operator ++ () { currentLink = currentLink->nextLink; }

    T operator * () { return currentLink->value; }

    bool operator == (ListIterator & right) 
    {   return currentLink == right.currentLink; }

private:
    Link * currentLink;
};


Containers in Java


UP to CSCI 581 Lecture Notes root document?


Copyright © 1999, H. Conrad Cunningham
Last modified: Wed Apr 21 16:59:26 CDT