Tuesday, November 6, 2007

Generic class definitions and one implementation

Generic class definitions and one implementation

Type parameterization goes in the horizontal direction while abstraction takes care of the 
vertical direction. The idea is the same, reusability and other OOP goodness. 

“The Class, the central notion in Object Technology, can be viewed as the product of the 
corporate merger between the module and type concepts.”

A generic class declared as C[G] is, rather than a type, a type pattern covering an infinite 
set of possible types; you can obtain any one of these by providing an actual generic 
parameter – itself a type - corresponding to G.

Java allows the use of wildcards to specify bounds on what type of parameters a given
 generic object may have. E.g. List indicates a list which has an unknown object 
type.  
List  is pronounced as List of Unknowns.

Void printCollection (Collection  c) {
 For (Object e : c)
     System.out.println(e);
} // will work for any collection of objects. 
   //But if the formal argument is Collection   then, it will not!

This is because, in general, if Parrot is a subtype (subclasss or subinterface) of 
Bar, and G is some Generic type declaration, it is not the case that G is a
subtype of G.

To specify the upper bound of a generic element, the extends keyword is used, which
 indicates that the generic type is a subclass (either extends the class, or 
implements the interface) of the bounding class.

So List means that the given list contains objects which extend the 
Shape class; for example, the list could be List or List.

To specify the lower bound of a generic element, the super keyword is used, which 
indicates that the generic type is a superclass of the bounding class.

So, List could be List or List or List.

Example Implementation: The  fictitious “formal generic parameter” here is E.

public class OopList {
 
 protected class Node{
  E element;
  Node next;
  Node (E e, Node n){ element = e; next = n; }
 }
 
 protected Node _head;
 
 
 /** Construct the empty List. */
 public OopList() { _head = null; }
 
 /** Add item to the beginning of the List. */
 
 public void add (E element) {
  _head = new Node (element, _head);
 }
 
 /** Return true iff this List is empty. */
 
 public boolean isEmpty() { return _head == null; }
 
 public String toString() {
  String x = "( ";
  while (!isEmpty()){
   x = x + this._head.element + " ";
   _head = _head.next;
  }
  return x + ")";
 }
 
 /** Allow iteration. */
 
 public java.util.Iterator elements() {
  return new OopListIterator (this);
 }
 
 public static void main (String [] args) {
  OopList OopLT = new OopList ();
  OopLT.add("Hello");
  OopLT.add("Not");
  OopLT.add("Done");
  
  System.out.println(OopLT.toString());
  
 }
} // End of class 



//********************************************************


// beginning of Iterator class. OopListIterator.

import java.util.*;

public class OopListIterator implements Iterator {
 
 private OopList _list;
 private OopList.Node _current;
 
 public OopListIterator (OopList list){
  _list = list;
  _current = _list._head;
 }
 
 public boolean hasNext () { return (_current != null); }
 
 public E next() throws NoSuchElementException {
  if (_current == null)
   throw new NoSuchElementException();
  E result = _current.element;
  _current = _current.next;
  return (result);
 }
 
 public void remove() throws UnsupportedOperationException {
  throw new UnsupportedOperationException();
 } 
  
 
}

//************************************************ Test Classes


public class Animal {

 protected String x;
 protected int age;
 protected boolean pet;
 
 public Animal (String y, int v, boolean i){
  x = y;
  age = v;
  pet = i;
 }
 
 public String toString (){
  String voila = "";
  voila = "Name: " + x + "  " +  "Age: " + age + " "+ " Pet: " + pet;
  return voila;
 }
 
 
 
 public static void main (String [] args){

  Animal me = new Animal ("Tiger", 33, true);
  System.out.println("Tiger is: ");
  System.out.println(me.toString());
 
  Animal Parrot1 = new Parrot ("P", 3, true);
  System.out.println("Parrot is: ");
  System.out.println(Parrot1.toString());
 }
}

//*****************************************

public class Parrot extends Animal {
  
  public Parrot (String x, int v, boolean z){
   super(x, v, z);
   this.x = "Parrot";
  }
  
 }


// JUNIT Testing:
//********************************************************

import junit.framework.TestCase;


public class OopListTest extends TestCase {

 public void OopListConstructorTest() {
  OopList OopLT = new OopList ();
  assertTrue (OopLT.isEmpty());
  
 }
 
 public void testOopList() {
  OopList OopLT = new OopList ();
  assertTrue (OopLT.isEmpty());
 }

 public void testAdd() {
  OopList OopLT = new OopList ();
  OopLT.add("Hello");
  OopLT.add("Not");
  OopLT.add("Done");
  assertEquals ("( Done Not Hello )", OopLT.toString());
  
 }

 public void testIsEmpty() {
  OopList OopLT = new OopList ();
  assertTrue (OopLT.isEmpty());
 }

 public void testElements() {
  OopList OopLT = new OopList ();
  OopListIterator iter1 = new OopListIterator (OopLT);
  assertFalse (iter1.hasNext());
  OopLT.add("Hello");
  OopLT.add("Not");
  OopLT.add("Done");
  OopListIterator iter = new OopListIterator (OopLT);
  
  assertFalse (OopLT.isEmpty());
  assertTrue (iter.hasNext());
  assertTrue (iter.hasNext());
  assertEquals("Done", iter.next().toString());
  assertEquals("Not", iter.next().toString());
  assertEquals("Hello", iter.next().toString());
  assertFalse (iter.hasNext());
 
 }
 
 /* Now let's try with another set of Objects 
  * Actual Generic Parameters in this case are Animal objects.
  * Type erasure and Generically derived type is Animal here.
  * */
 
 
 public void testElements3() {
  OopList OopLT = new OopList ();
  assertTrue (OopLT.isEmpty());
  OopListIterator iter1 = new OopListIterator (OopLT);
  assertFalse (iter1.hasNext());
  
  Animal me = new Animal("Tiger", 33, true);
  
  Animal horse = new Animal("Horse", 10, true);
  
  Animal Parrot1 = new Parrot ("P", 3, true);
  OopLT.add(Parrot1);
  OopLT.add(horse);
  OopLT.add(me);
  OopListIterator iter = new OopListIterator (OopLT);
  assertFalse (OopLT.isEmpty());
  assertTrue (iter.hasNext());
  assertTrue (iter.hasNext());
  assertEquals("Name: Tiger  Age: 33  Pet: true", iter.next().toString());
  assertEquals("Name: Horse  Age: 10  Pet: true", iter.next().toString());
  assertEquals("Name: Parrot  Age: 3  Pet: true", iter.next().toString());
  assertFalse (iter.hasNext());
  OopListIterator iter2 = new OopListIterator (OopLT);
  assertTrue (iter2.hasNext());
  assertTrue (iter2.hasNext());
  assertEquals("Name: Tiger  Age: 33  Pet: true", iter2.next().toString());
  assertEquals("Name: Horse  Age: 10  Pet: true", iter2.next().toString());
  assertEquals("Name: Parrot  Age: 3  Pet: true", iter2.next().toString());
}
}

// Adopted from: http://www.cs.huji.ac.il/course/2005/oop/lecture-slides.html


No comments:

Just some daily notes ...

Powered By Blogger