A class is a bundle of data and optionally functions that act on that
data.  Here's an example of a simple data-only class:
     class location
         {
	 string name;
	 int x,y;
	 }
The data items - name, x, and y - are known as members
of the class.

To create an instance of a class (also known as an object)
you initialize a variable of the class type as so:
      location center = ("center", 0, 0);
The class name is followed by the variable name, followed
by an equals sign, and then a parenthesized list containing
the initial value of each member.

The members of a class are accessed by
the dot operator as so:
      string locName = location.name;
or
      location.x += 10;
      location.y += 10
The classVariable.classElement combination can be used almost
anywhere a simple variable can be used.  

Class variables can also be declared without initialization
as so:
     location loc;
In this case the variable loc has the value we call 'nil'.
About all that you can do with a nil-valued variable is
to test it:
     if (loc)
         print("The loc is called " + loc.name);
     else
         print("Nothing has been assigned to loc yet.");
Generally you will want to initialize your objects as you
declare them,  but on occassion it can be useful to declare
first and initialize later.

You can also initialize an object as so:
      location loc = ();
This will create an object with members that are initialized
to default values.  You can specify default values in the
class declaration.  If no values are specified the default
values are zero for numerical elements, and nil in all of the 
string and object elements.   Here is an example of a class
with default values for it's members:
      class location
          {
	  string name = "off-center";
	  int x=1,y=2;
	  }
Note that the "=0" for x and y don't actually do anything,
size 0 is assumed in the absense of any initialization.
You could create instances of this class any of the following
ways:
	location loc = ()   [equivalent to ("off-center", 1, 2)]
	location loc = ("here") [equivalent to ("here", 1, 2)]
	location loc = ("there",3) [equivalent to ("there",3,2)]
	location loc = ("center",0,0)  [fully specified]

Classes can contain functions as well as data.  A
class function, which is called a "method" for short,
is defined by declaring a function inside of a class.
Member functions are implicitly passed the object
they are associated with in a variable called "self".
Here is a location class with a method defined for
moving it:
     class location
         {
	 string name;
	 int x,y;
	 to move(int dx, int dy)
	     {
	     self.x += dx;
	     self.y += dy;
	     }
	  }
Invoking a method uses a dot syntax similar to accessing a data
member as illustrated in this fragment of code:
      location loc = ("here", 20, 30);
      loc.move(-20, -30);

It's possible for multiple variables to refer to the same object.
This saves memory, makes binary trees and other advanced data
structures possible, and is generally a good thing.  In some
cases it can have surprising results though.  Consider this
snippet of code:
      location center = ("center", 0, 0);
      location offCenter = center;
      offCenter.move(1,1);
After the second line of code both center and offCenter refer
to the same object.  Thus if you were to print out center you
would see:
      ("center", 1, 1)
If you didn't want this behavior instead you would code it as
      location center = ("center", 0, 0);
      location offCenter = (center.name, center.x, center.y);
      offCenter.move(1, 1);

Sometimes it is convenient to define a class largely in terms
of another class.  This is done with the 'extends' keyword.
Imagine you were creating a program to describe items for sale
in a store.  A basic class might be
      class item
         {
	 string name;
	 float price;
	 }
Some items might be perishable and need to be replaced at a certain
date.  You could code this as so:
      class perishableItem
          {
	  string name;
	  float price;
	  string expirationDate;
	  }
This would work, but would have two disadvantages.  First you'd
have to type int the first two members twice.  More importantly any
functions that worked on items would not work on perishable items.
It'd be better to code the perishables as so:
      class perishableItem extends item
          {
	  string expirationDate;
	  }
You'd create variables of these classes as so:
      item salt = ("salt", 1.23);
      item milk = ("milk", 2.59, "2005-04-21");
You could then write a function that calculated the tax on
an item as so:
      to tax(item item) into float tax
      {
      tax = item.price * 0.075;
      }
and apply this either to perishable or normal items:
      saltTotal = salt.price + tax(salt);
      milkTotal = milk.price + tax(milk);

The extends keyword thus allows you to create a heirarchy
of classes.  In many situations a well constructed class
heirarchy can allow you to write very concise and flexible
code.  However some care should be taken.  A class heirarchy
introduces dependencies between code at various levels of
the hierarchy.  It can be frustrating to have useful code
buried in a member function that you can't reuse without
having to reuse the whole heirarchy.  In real life our
tax function might be better coded as so:
     to tax(float untaxed) into tax
     {
     tax = untaxed * 0.075;
     }
so that it could be used independently of any class heirarchy.

Within a class certain methods can be declared as "polymorphic."
Polymorphic functions can be redefined in child classes.  
Here's an example of polymorphism in action:
     class animal
         {
	 string name;
	 polymorphic to sound() into string s
	     {
	     s = "???";  // We don't know what sound an animal makes
	     }
	 to speak()
	     {
	     print(self.name + " says " + self.sound());
	     }
	 }
This defines a class with two methods.  The polymorphic sound 
method returns a string representing the sound the animal makes.
The speak method prints the animal's name and sound.  We could
extend this to two more classes as so:
      class dog extends animal
          {
	  polymorphic to sound() into string s
	      {
	      s = "bark";
	      }
	  }
      class cat extends animal
          {
	  polymorphic to sound() into string s
	      {
	      s = "meow";
	      }
	  }
and even extend one of these further
      class toyPoodle extends dog
          {
	  polymorphic to sound() into string s
	      {
	      s = "yip";
	      }
	  }
In a typical use of polymorphism we might create an array
of animals as so:

dog fido = ("Fido");
dog bruiser = ("Bruiser");
cat rags = ("Ragland B. Tuttle");
toyPoodle fifi = ("Fifi");

array of animals pets = (fido, bruiser, rags, fifi)

We could then ask each animal in the array to speak as so:
     for (a in pets)
         a.speak()
This would print the result:
     Fido says bark
     Bruiser says bark
     Ragland B. Tuttle says meow
     Fifi says yip

Note that without the polymorphic keyword ParaFlow will give an
error if a method that is present in a parent class is redefined
in an extended class.  ParaFlow does not allow data members in
a parent to be redefined at all.  This is a concious decision.
While this redefinition (called overloading in the object-oriented
literature) is convenient in some cases, it can be difficult to
tell just by reading the code which function is being called in
an overloaded system,  particularly since class heirarchies
can be spread out across large sections of the source code.  

NB: In the future paraFlow might let you give separate initialization
values for members of extending classes.
