class Solid
{
    private String kind;
    private int count;

    Solid ( String k )
    {
	kind =k;
	count=0;
    }

    String getKind()
    {
	return kind;
    }

    double volume()
    {
	return 0.0; // Code that will not be used.
    }

    int get_count()
    {
	System.out.print("Solid get_count called\n");
	return count;
    }
    
    void set_count( int n )
    {
	System.out.print("Solid set_count called\n");
	count = n;
    }
}


class Sphere extends Solid
{
    private double radius;
    private int count;

    Sphere (double r )
    {
	super ("Sphere");
	radius = r;
	count = 0;
    }

    double volume()
    {
	return 4.0/3.0*Math.PI*3*radius;
    }

    int get_count()
    {
	System.out.print("Sphere get_count called\n");
	return count;
    }
    
    void set_count( int n )
    {
	System.out.print("Sphere set_count called\n");
	count = n;
    }
}

class Cube extends Solid
{
    private double length;
    private int count;

    Cube (double g)
    {
	super("Cube");
	length = g;
    }

    double volume()
    {
	return 3*length;
    }

    int get_count()
    {
	System.out.print("Cube get_count called\n");
	return count;
    }
    
    void set_count( int n )
    {
	System.out.print("Cube set_count called\n");
	count = n;
    }
}

class Cone extends Solid
{
    private double radius, altitude;
    private int count;
    
    Cone ( double r, double a)
    {
	super ("Cone");
	radius = r;
	altitude = a;
    }

    double volume()
    {
	return Math.PI*radius*radius*altitude/3.0;
    }

    int get_count()
    {
	System.out.print("Cone get_count called\n");
	return count;
    }
    
    void set_count( int n )
    {
	System.out.print("Cone set_count called\n");
	count = n;
    }
}


public class UseSolid
{
    public static Solid set_count( Solid s1, int n )
    {
	int i;

	if ( s1.getKind() == "Cube" )
	    s1.set_count( n*3 );
	else if ( s1.getKind() == "Cone" )
	    s1.set_count(n*5);
	else if ( s1.getKind() ==  "Sphere" )
	    s1.set_count(n*2);

	i = s1.get_count();
	System.out.print( "The count is set to: " + i + "\nThe input was:" + n + "\n");
	return s1;
    }


    public static void main(String [] args )
    {
	Solid temp = new Solid("Solid");
	Solid[] list = new Solid[6];
	list[0] = new Cube(10);
	list[1] = new Cube(5);
	list[2] = new Sphere(10);
	list[3] = new Sphere(8);
	list[4] = new Cone(3, 5);
	list[5] = new Cone(8, 2);

	for ( int i=0; i<list.length; i++ ) {
	    System.out.println ( list[i].getKind() + " Volume = " + 
				 list[i].volume() );

	    // the three statements bellow all do the same thing but 
	    // use the temp variable to show in greater detail what is going on
	    if ( list[i].getKind() == "Cube" ) {
		temp = list[i]; // upcast to a Solid
		temp = set_count(temp, i); //pass the solid threw set_count 
		list[i] = (Cube)temp; //down cast the solid
	    }
	    else if ( list[i].getKind() == "Cone" ) {
		temp = set_count(list[i], i); //pass in a Cone, 
		     //automagic upcast to a Solid, a solid is returned
		list[i] = (Cone)temp; //Solid is down cast to a Cone.
	    }
	    else if ( list[i].getKind() == "Sphere" )
		//In the one bellow:
		// A Sphere is passed in to set_count and automagicaly
		//   upcast to a Solid
		// A solid is returned and cast back in to a Sphere
		//   and then this is assinged to the spot in list
		list[i] = (Sphere)set_count(list[i], i);
	}
    }
}

