
// class for a generic cell of a linked list:
class gcell
{
public  Object head;    // Object is ultimate superclass
public  gcell tail;

public gcell(Object h, gcell t)
    { head = h;   tail = t; }
} // end class gcell


abstract class plist  // polymorphic list class
{
    gcell front;  // point to front of gcells
    // polymorphic methods. 

// non-polymorphic function:
abstract boolean equal(Object a, Object b);  // will be defined in subclasses


// polymorphic functions:

    // is X in list?
public boolean member(Object X)
    {  gcell ptr = front;
       boolean ax = false;
       while (ptr != null)
	   {  ax = ax || equal(X,ptr.head);
              ptr = ptr.tail;
           } // end while
       return ax;
    } // end member;

public  int length()
    {   int ax = 0;
        gcell ptr = front;
        while (ptr != null)
	    { ax++;
              ptr = ptr.tail;
            }
        return ax;
    } // end length
} // ends plist


// subclasses:

class strlist extends plist
{
public String firstString()   // subclass-specific function
    { return (String) front.head;
    }

boolean equal(Object a, Object b) // header must match abstract declaration
    {  String sa = (String) a;  // type cast Object to String;
       String sb = (String) b;
       return sa.equals(sb);
    }

} // end strlist

class rational    // simple class representing fraction n/d
{ int n;
  int d;
    rational(int a, int b) { n = a; d  = b; }
} // rational


class ratlist extends plist
{
  rational firstrat() { return (rational) front.head; }

  boolean equal(Object a, Object b)
    {  rational ra, rb;
       ra = (rational) a;
       rb = (rational) b;
       return (ra.n*rb.d) == (ra.d*rb.n);
    }
}

public class polylist
{
public static void main(String[] args)
    {
       String s1 = "you";
       String s2 = "me";
       rational r1 = new rational(1,2);
       rational r2 = new rational(2,5);
       strlist myslist = new strlist();
       ratlist myrlist = new ratlist();
      
       myslist.front = new gcell(s1,new gcell(s2,null));
       myrlist.front = new gcell(r1,
			  new gcell(r2,null));

       System.out.println(myslist.length() + "   " +
			  myrlist.length());
       System.out.println(myslist.member("me") + "    "
		   + myrlist.member(new rational(3,6)));

    } // end main
}
    
  
