View
39
Download
0
Category
Preview:
DESCRIPTION
Type Hierarchies. Type Hieararchy. Why?: Want to define family of related types. At the top of the hierarchy, a type whose spec defines behavior common to all family members Two different ways: Multiple implementations of a type: Two-level hieararchy Example: phoneBook w/ Hashtable - PowerPoint PPT Presentation
Citation preview
Type Hierarchies
Type Hieararchy Why?: Want to define family of related types. At the top of the hierarchy, a type whose spec defines behavior common to
all family members Two different ways:
1. Multiple implementations of a type: Two-level hieararchy
Example: phoneBook w/ Hashtable phoneBook w/ Vector
Different types do not add any new behavior Except, each has its own constructors
2. Different subtypes extend behavior of their supertypes Examples: Additional methods
Supertype’s behavior must be satisfied by subtype Called the substitution principle
The “is” relationship Can replace an object of the subtype whenever object of the supertype is
required
Assignment Apparent vs. actual type Suppose
Poly p1 = new DensePoly(); // the zero PolyPoly p2 = new SparsePoly(3, 20); // the Poly 3x20
Variable of type Poly can refer to DensePoly or SparsePoly objects Compiler does checking based on apparent type
Cannot invoke a DensePoly only method on p1 But
DensePoly dp = (DensePoly) p1; dp.densePolyMethod() …is legal
Poly
DensePolySparsePoly
Dispatching Example:
Poly p1 = new DensePoly();int n = p1.degree();
Both Poly and DensePoly have their own version of the degree() method
ExampleStatic Poly diff(Poly p) {
//differentiates pint g = p.degree();...
}
Dispatching: Figuring out which one to call Checking done based on apparent type Execution during run-time based on actual type
Defining a Type Hierarchy First step: Define type at top of hierarchy
May not be a complete specification May lack constructors, some methods
Subtypes Provide constructors Additional methods Change behavior of some supertype methods
Good programming practice allows only limited changes Must provide new specification
Subtype implementations contain Instance variables defined in supertype Methods provided in supertype
Except private constructors
Defining Hierarchies Supertypes come in three flavors
Classes (concrete classes): All methods implemented
Abstract classes Some methods implemented, some not Some fields No objects of an abstract class
Interfaces No methods implemented Why have these?
ActionListener example
Defining Hierarchies Methods
Normal vs. final methods Final methods cannot be overridden
Abstract methods Methods with no implementations
These distinctions interesting only to implementors Not to users!!!
Representations for subtypes include instance variables for Supertype and itself
Subtype can access supertype fields (instance variables) only if declared as protected But protected variables are also package visible
Better if subclass only accesses superclass through public interface. Gives full modularity.
A Simple Examplepublic class IntSet {
//OVERVIEW: IntSets are mutable , unbounded sets of //integers. A typical IntSet is {x1, ... , xn}//constructorspublic IntSet()
//EFFETCS: Initializes this to be empty.//methodspublic void insert (int x)
//MODIFIES: this//EFFETCS: Adds x to the elements of this.
public void remove (int x)//MODIFIES: this//EFFECTS: Removes x from this.
public boolean inIn (int x)//EFFECTS: If x is in this returns true else
//returns false.
Continued next page
A Simple Examplepublic int size ()
//EFFETCS: Returns the cardinality of this.public boolean subset (IntSet s)
//EFFECTS: Returns true if this is a subset of s //else returns false.
}
A Simple Examplepublic class IntSet {
private ArrayList<int> els; // the elementspublic IntSet () { els = new ArrayList<int> (); }private int getIndex (Integer x) { ... }private boolean isIn (int x) {
return getIndex(new Integer(x)) >= 0; }public boolean subset (IntSet s) {
if (s == null) return false;for (int i = 0; i < els.size(); i++)
if (!s.is In(((Integer) els.get(i)).intValue()))return false;return true; }
// implementations of other methods go here} Observe
No protected methods Concrete class: All methods implemented
public class MaxIntSet extends IntSetpublic class MaxIntSet extends IntSet {
//OVERVIEW: MaxIntSet is a subtype of IntSet with an //additional method, max, to determine the maximum //element of the set.
//constructorspublic MaxIntSet ()
//EFFECTS: Makes this to be empty MaxIntSet.
//methodspublic int max () throws EmptyException
// EFFECTS: If this is empty throws EmptyException // else returns the largest element of this.
} Only new methods need to be specified New field:
private int biggest;//the max element (if set is not empty)
MaxIntSet Constructorpublic MaxIntSet () { }
automatically calls
public MaxIntSet () { super() };
Subtype constructor must call supertype constructor Otherwise, supertype constructor with no arguments is called
automatically
MaxIntSet Implementationspublic class MaxIntSet extends IntSet {
private int biggest; //the biggest element if set is not empty
public MaxIntSet () { super(); }
public void insert (int x) {if (size () == 0|| x > biggest) biggest = x;super.insert(x); }
public void remove (int x) {super.remove(x);if (size() == 0 || x < biggest) return;Iterator g = elements();biggest = ((Integer) g.next()).intValue();while (g.hasNext() {
int z = ((Integer) g.next()).intValue();if (z > biggest) biggest = z; }
}
Continue next page
A Simple Examplepublic int max () throws EmptyException {
if (size() == 0) throw new EmptyException (“MaxIntSet.max);return biggest;
}}
Abstract Classes Abstract class: Partial implementation of a type May have instance variables, constructors, implementation of some
methods Constructors initialize supertype’s portion of the implementation
Allows code reuse, reliability Some methods left unimplemented
Called abstract methods
public boolean subset (IntSet s) //inheritedpublic boolean subset (SortedIntSet s) // extra
Abstract Classespublic class SortedIntSet extends IntSet {
//OVERVIEW: A sorted int set is an int set whose elements are //accessible in sorted order.//constructors:public sortedIntSet()
//EFFECTS: Make this be an empty sorted set//methods:public Iterator elements()
//EFFECTS: Returns a generator that will produce all //elements of this, each exactly once, in ascending order.
//REQUIRES: this not be modified while the generator is in use.public int max() throws EmptyException
//EFFECTS: If this is empty throws EmptyException else //returns the largest element of this.public boolean subset (SortedIntSet s)
} has two subset methods
public boolean subset (IntSet s) //inherited, no specpublic boolean subset (SortedIntSet s) // extra, for
// better performance
Abstract Classes If subtype wants to use its own rep and not use the supertype’s,
there’s no way to do so In that case, make supertype abstract
No rep, therefore no objects of that type No way for users to call constructor of abstract supertype
Abstract Classespublic abstract class IntSet {
protected int sz; // the size
//constructorspublic IntSet () { sz = 0; }
//abstract methodspublic abstract void insert (int x);public abstract void remove (int x);public abstract Iterator elements ();public abstract boolean reOk ();
Continued next page
Abstract Classes//methods
public boolean isIn (int x) {Iterator g = elements ();Integer z = new Integer(x);while (g.hasnext())
if (g.next().equals(z)) return true); return false; }
public int size () { return sz; }// implementations of subset and toString go here
publıc boolean subset (IntSet otherSet)} size() could have been implemented using the elements() iterator
But would be inefficient All subtypes need efficient size() implementation
Provide field sz and size() implementation Allow subtypes access to sz
Interfaces Interfaces
Define a type Provide no implementation
Useful for providing multiple supertypes Can implement many interfaces But can extend only one class
public class SortedIntSet extends ıntSetimplements sortedCollection { ... }
Interfacespublic interface Iterator {
public boolean hasNext ();//EFFECTS: Returns true if there are more items
to //produce else returns false.public Object next () throws NoSuchElementException;
//MODIFIES: this//EFFECTS: If there are no more items to produce, //throw NoSuchElementException. Otherwise retuns //the next item and changes the state of this to //reflect the return.
}
Multiple Implementations Different implementations of a type
Some implementations more efficient for a subset of objects E.g. Sparse vs. dense polynomials
Implementation subclasses invisible to users Only referred to when creating new objects
Poly p1 = new DensePoly();Poly p2 = new SparsePoly();
After some manipulation, p1 may refer to a SparsePoly and p2 may refer to a DensePoly
Multiple Implementations Example: Listspublic abstract class IntList {
//OVERVIEW: IntLists are immutable lists of Objects. A //typical IntList is a sequence [x1,..., xn].//methodspublic abstract Object first () throws EmptyException;
//EFFECTS: If this is empty throws EmptyException //else returns the first element of this.
public abstract Intlist rest () throws EmptyException;//EFFECTS: If this is empty throws EmptyException //else returns the list containing all but the //first element of this, in the original order.
public abstract Iterator elements ();//EFFECTS: Returns a generator that will produce //the elements of this, each exactly once, in the //order in this.
Continue next page
Listspublic abstract IntList addEl (Object x);
public abstract int size ();//EFFECTS: Returns a count of the number of
//elements of this.public abstract boolean repOk ();public String toString ()public boolean equals (IntList o);
}
List Implementation as Abstract Classpublic abstract class IntList {
//OVERVIEW: Intlists are immutable lists of objects. A typical IntList is a sequence [x1, ..., xn]//abstract methodspublic abstract Object first () throws EmptyException;public abstract IntList rest () throws EmptyException;public abstract Iterator elements ();public abstract IntList addEl (Object x);public abstract int size ();
//methodspublic String toString () { ... }
Continue next page
List Implementation as Abstract Classpublic boolean equals (Object o) {
try { return equals ((IntList) o); }catch (ClassCastException e) { return false; }
}public boolean equals (IntList o) {
//compare elements using elements iterator}
}
Implementation 1: Empty Listpublic class EmptyIntList extends IntList {
public EmptyList () { };public Object first () throws EmptyException {
throw new EmptyException(“EmptyIntList.first”); }public IntList addEl (Object x) { return new FullIntList(x); } // not independent of // other implementationpublic boolean repOk () { return true); }public String toString () { return “IntList: []”; }public boolean equals (Object x) { return (x instanceof EmptyIntList); }//implementations of rest ans size go herepublic Iterator elements () { retun new EmptyGen(); }
Continue next page
Implementation 1: Empty Liststatic private class EmptyGen implements Iterator {
EmptyGen () { }public boolean hasNext () { return false; }public Object next() throw NoSuchElementException
{throw new
NoSuchElementException(“IntList.elements”); }} //end EmptyGen
}
Continue next page
Implementation 2: FullIntListPublic class FullIntList extends IntList {
private int sz;private Object val;private IntList next;public FullIntList (Object x) {
sz = 1; val = x; next = new EmptyIntList(); } // not independent of other implementation
public Object first () { return val; }public Object rest () { return next; }public IntList addEl (Object x) {
FullIntList n = new FullIntList(x);n.next = this;n.sz = this.sz + 1;return n; }
// implementations of elements, size, repOk go here}
Example: Polynomial Superclasspublic abstract class Poly {
protected int deg; //the degree
//constructorprotected Poly (int n) { deg = n; }
//abstract methods coeff, repOk, add, mul, minus, terms//methods
public int degree () { return deg; }
public boolean equals (Object o) {try { return equals((Poly) o); }catch (ClassCastException e) { return false; }
}
Continue next page
Polynomialspublic boolean equals (Poly p) {
if (p == null || deg != p.deg) return false;Iterator tg = terms();
Iterator pg = p.terms();while (tg.hasNext()) {
int tx = ((Integer) tg.next()).intValue();int px = ((Integer) pg.next()).intValue();if (tx != px || coeff(tx) != p.coeff(px) return false); }
return true; }public sub (Poly p) { return add(p.minus()); }public String toString () { ... }
}
Implementation 1: DensePolyprivate class DensePoly extends Poly {
private int[] trms; //coefficients up to degreeprivate DensePoly () {
super(0); trms = new int[1]; }public DensePoly (int c, int n) throws NegExpExceptio { ... }private Densepoly (int n) {
super(n); trms = new int[n+1]; }
//implementation of coeff, add, mul, minus, terms and repOk go herepublic Poly add (Poly q) throws NullPointerException {
if (q instanceof SparsePoly) return q.add(p);DensePoly la, sm;
Continue next page
if (deg > q.deg) { la = this; sm = (DensePoly) q; }
else { la = (DensePoly) q; sm = this; }
int newdeg = la.deg; // new degree is the larger // degreeif (sm.deg == la.deg) // unless there are trailing // zeros
for (int k = sm.deg; k > 0; k--)if (sm.trms[k] + la.trms[k] != 0)
break; else newdeg--;
DensePoly r = new DensePoly(newdeg); //get a new //densePolyint i;for (i = 0; , i <= sm.deg && i <= newdeg; i++)
r.rtms[i] = sm.trms[i] + la.trms[i];
for (int j = i; j <= newdeg; j++) r.trms[j] = la.trms[j];
return r; }}
How to enable users to ignore different implementations?
Make new “factory” class
public class polyProcs {public static Poly makePoly ()
//EFFECTS: Returns the zero Poly.return new DensePoly()
public static Poly makePoly (int c, int n) throws NegExpException
//EFFECTS: If n < 0 throws NegExpException //else returns the monomial cxn.return new SparsePoly(c comma n)
}
Recommended