/** demonstrate subclass, overriding method, and protected instance 
    variable. */
public class ThreeDPoint extends TwoDPoint {
// the subclass inherits all varibles and methods of the superclass
  private int z;  

  public ThreeDPoint() {
    super();  // call the superclass's constructor
    z = 0;
  }
  public ThreeDPoint(int r, int s, int t) {
    super(r, s);
    z = t;
  }
  public ThreeDPoint(ThreeDPoint p) {
    this(p.getX(), p.getY(), p.getZ());  // call own constructor
  }

  // public access methods
  public int getZ() {
    return z;
  }
  public void changeZ(int r) { // anybody can change the z coordinate
    z = r;
  }
  /* this distance method overrides that of the base class */
  public double distance(ThreeDPoint p) { 
    return Math.sqrt((double)(this.getX() - p.getX())*(this.getX() 
                    - p.getX()) + (this.getY() - p.getY())*(this.getY() 
                    - p.getY()) + (this.getZ() - p.getZ())*(this.getZ() 
                    - p.getZ()));
  }

  /* test the ThreeDPoint class */
  public static void main(String args[]) {

    // create 3 ThreeDPoint objects
    ThreeDPoint p0 = new ThreeDPoint();
    ThreeDPoint p1 = new ThreeDPoint(1, 2, 3);
    ThreeDPoint p2 = new ThreeDPoint(1, 5, 7);

    /* create a new object identical to p1 */
    ThreeDPoint p3 = new ThreeDPoint(p1);  
    ThreeDPoint p4 = p2;  // p4 and p2 refer to the same object

    // the following two results are identical
    System.out.println(p1.distance(p2)); /* sends the message 
                                        "distance(p2)" to object p1 */
    System.out.println(p2.distance(p3));

    p4.z = 10;  /* ok because the main() method is in the same class 
                 (although instance variable z is private); it won't be 
                  ok if it were p4.x = 10 */
    System.out.println(p1.distance(p2)); // p2's z coordinate is now 10 

    /* prefix a static variable with the class name */
    System.out.println(ThreeDPoint.countPoints);  

    TwoDPoint q1 = new TwoDPoint(); // create a TwoDPoint object
    q1 = p1;  // ok, but p1 = q1 results in incompatible types error
    p2 = (ThreeDPoint)q1;  // use type casting
    System.out.println(p2.getZ());  // print p1's z coordinate at runtime
    System.out.println(q1.toString());

    TwoDPoint q2 = new TwoDPoint(10, 20); // create a TwoDPoint object
    p3 = (ThreeDPoint)q2;  /* use type casting, note that the 
                              "original" p3 object is now garbage;
                              the statement results in runtime error, 
                              but no compile-time error */
  }
}

