250 likes | 464 Views
Containers. CMPS 2143. Reusable containers. Simple data structures in almost all nontrivial programs Examples: vectors, linked lists, stacks, queues, binary trees, sets, dictionaries, etc. So common expect ideal for development as reusable components.
E N D
Containers CMPS 2143
Reusable containers • Simple data structures in almost all nontrivial programs • Examples: vectors, linked lists, stacks, queues, binary trees, sets, dictionaries, etc. • So common expect ideal for development as reusable components
Containers in dynamically typed languages: • Easier in dynamically typed languages to produce reusable containers • Often those languages have them built-in • Easier because value retains knowledge of its type (self referential) • Also dynamic languages permit values of different classes heterogeneous collections
Look at several collections • abstractCollection • can add, remove, get size, check if empty, … • Set - inherits/overrides/adds Collection methods • a set is an unordered Collection of unique elements • Dictionary – inherits/overrides/adds methods • a dictionary is a Set where each element of the set is an Association representing a single key/value pair • Bag –inherits/overrides/adds Collectionmethods • a bag is similar to a set, but values do not have to be unique • Bag will also use composition
inheritance as mechanism for specialization (Set and Bag) • deferred methods (add and remove in Collection) • inheritance as mechanism for construction (Dictionary)
composition (Bag has a dictionary) • key is the element in the bag • value is the number of times element is in the bag
Containers in Statically Typed Languages • Static typing can interfere with software reuse • 3 solutions • Use principle of substitution to store values in a container and combine with down casting (reverse polymorphism) when values removed from container • Use principle of substitution but avoid down casting through use of overriding • Use generics or templates
C++ Linked list of integers class List { public: //methods void insert (int newVal); private: class Node { //Node is an inner class public: // inside class List int value; // so okay for public data Node * next; }; … Node * head; };
Concerns • Question of reusability • suppose we now want a list of doubles • Problem: conventional static languages are too strongly typed • int data type is intrinsic part of definition • But OOP languages can utilize • principle of substitution and generics
Substitution and downcasting class List { public: //methods void insert (Object newVal); Object removeAt (int index); private: class Node { //inner class public: Object value; Node * next; }; … Node * head; };
Substitution and downcasting List catList; Cat aCat (“Leo”); Dog aDog (“Fido”); catList.insert(aCat); Cat bCat = (Cat) catList.removeAt (1); //downcasting from //Object to Cat catList.insert(aDog); //aDog is an Object, no compiler error Cat bCat = (Cat) catList.removeAt (1); //OOPS! NOW error!
Notes: • Can only have heterogenouscollections if there is a super Object in the language (as in Java). • Even so cannot include primitive types (int, double, char, … do not inherit from Object) • solution is to have a wrapper class • class Double to hold a double value with get/set methods • Java has some built-in
Using substitution and overriding • A cast expression is often considered to be NOT truly object-oriented • Can avoid with use of substitution combined with method overriding • only possible if original developer knows how an object will be used (even if they don’t know the type of value stored in container) • Used in a few restricted situations
C#, Java example • Events handled by Listener objects that are attached to a container like a Window object. • When event occurs in a given window, all registered listeners are notified • mouse movement, mouse pressed, key pressed, text box changed, etc. • Java also provides adapters that implement interfaces • Programmer defines a class to implement interface and overrides the methods they want
Parameterized classes • using principle of substitution in previous 2 techniques is only suitable if there is a parent class that can be used as basis • if a language does not have a single root that is ancestor to all classes, then… use generics.
Templates #pragma once template <class ItemType> class List { public: //methods void insert (ItemTypenewVal); ItemTyperemoveAt (int index); private: class Node { public: ItemTypevalue; Node * next; }; … Node * head; }; #include “List.cpp”
Templates • To use List <int> intList; List <double> doubleList; • In this way, homogeneous lists can be created • Book says you can’t have heterogeneous lists, but as long as you use references… List <Shape *> shapeList;
Element traversal on Containers • Provides method that allow you to loop over the elements in the container boolhasMoreElements(); //return true iff there are more elements to process ItemTypenextElement(); //return next element void reset(); //start at first element
Iterator methods template <class ItemType> class List { public: void insert (ItemTypenewVal); ItemTyperemoveAt (int index); void resetCursor(); void advanceCursor(); boolcursorAtEnd(); ItemTypenextElement (); private: class Node { public: ItemTypevalue; Node * next; }; … Node * head; Node * cursor; //for iteration };
#include “List.h” #include <iostream> using namespace std; void List:: resetCursor(){cursor = head;} void List:: advanceCursor() { if (cursor != null) cursor = cursor->next; else cout << “Error: Cannot advance cursor, cursor at end \n”; } boolList:: cursorAtEnd(){return cursor == null}; ItemTypeList:: nextElement (){ if (cursor != null) return cursor->value; else cout << “Error: Cannot advance cursor, cursor at end \n”; }
#include “List.h” #include <iostream> using namespace std; template <class ItemType> void loadList (List <ItemType> & list); template <class ItemType> void sumList(List <ItemType> & list, ItemType & sum); void main() { List <int> intList; int sum = 0; loadList (intList); sumList (intList, sum); cout << “Sum of items in list is “ << sum << endl; system(“pause”); }
template <class ItemType> void loadList (List <ItemType> & list) { list.insert(1); list.insert(2); list.insert(5); } template <class ItemType> void sumList(List <ItemType> & list, ItemType & sum) { list.resetCursor(); while (!list.cursorAtEnd()) { i = list.nextElement(); sum += I; list.advanceCursor(); } }
#include “List.h” #include “ComplexNumber.h” #include <iostream> using namespace std; template <class ItemType> void loadList (List <ItemType> & list); template <class ItemType> void sumList(List <ItemType> & list, ItemType & sum); void main() { List <ComlexNumber> intList; ComplexNumbersum; //default constructor sets sum = 0+0i loadList (intList); sumList (intList, sum); cout << “Sum of items in list is “ << sum << endl; system(“pause”); }
Visual Studio STL containers • http://msdn.microsoft.com/en-us/library/1fe2x6kt(v=vs.110).aspx
Study • pg. 387: 1, 3, 5