Experiments in Java


Experiments for Session O2: Inheritance

Name: ________________
ID:_______________

Experiment O2.1: Building a new point class

Required files:

Step 1. Make copies of Point.java, PointFun.java, and NewPoint.java. Compile all three and execute PointFun. Record your results.


 
 
 
 
 
 

Step 2. Replace the line in PointFun that reads

    Point pt = new Point(2,3);

with

    Point pt = new Point();

Recompile PointFun and execute PointFun. Record your results.


 
 
 
 
 
 

Step 3. Make a copy of PointFun.java called NewPointFun.java (you'll also have to change PointFun to NewPointFun within the code). Update NewPointFun to use a NewPoint wherever it used a Point. Summarize your changes here.


 
 
 
 
 
 

Step 4. Compile and execute NewPointFun. Record your results. Are they the same as in step 2?


 
 
 
 
 
 

Step 5. Update the zero-parameter constructor for Point to read

  /**
   * Build the point (1,1).
   */
  public Point() {
    this.xcoord = 1;
    this.ycoord = 1;
  } // Point()

Do not change NewPoint or NewPointFun. Recompile Point and run NewPointFun. Record and explain the output.


 
 
 
 
 
 

Step 6. As you may have observed, the zero-parameter constructor for NewPoint no longer creates the point (0,0). Update that constructor so that it always creates that point. Summarize your changes here.


 
 
 

Step 7. Record any general observations you have about the process of creating a variant of the Point class in this experiment.


 
 
 
 
 
 

Experiment O2.2: A simple extension of the Point class

Required files:

Step 1. Make fresh copies of Point.java and PointFun.java. Compile the two programs. Execute PointFun. Record the results.


 
 
 
 
 
 

Step 2. Build a new ExtendedPoint class containing only the following lines along with an appropriate introductory comment.

public class ExtendedPoint
  extends Point {
} // class ExtendedPoint

Compile the new class and record any error messages you receive. After doing so, read the notes on this step.


 
 
 

Step 3. Modify PointFun to use an ExtendedPoint in place of each Point. Summarize your changes.


 
 
 
 
 
 

Step 4. Attempt to compile the new class and record any error messages you receive. What do these error messages suggest? After writing your answer, read the notes on this step.


 
 
 
 
 
 

Step 5. Change the line in PointFun's main method that creates the point from

    ExtendedPoint pt = new ExtendedPoint(2,3);

to

    ExtendedPoint pt = new ExtendedPoint();

Recompile and execute PointFun. Record the output. What does this suggest?


 
 
 
 
 
 

Step 6. Add the following constructor to ExtendedPoint.

  /**
   * Build the point (x,y).
   */
  public ExtendedPoint(double x, double y) {
    setValue(x,y);
  } // ExtendedPoint(double, double)

Recompile both PointFun and ExtendedPoint. If you are successful, record and explain the results. If you are not successful, record and explain the error messages.


 
 
 
 
 
 

Step 7. Add the following constructor to ExtendedPoint.

  /**
   * Build the point (1,1).
   */
  public ExtendedPoint() {
    setValue(1,1);
  } // ExtendedPoint()

Recompile both PointFun and ExtendedPoint. If you are successful, record and explain the results. If you are not successful, record and explain the error messages.


 
 
 
 
 
 

Step 8. Change the line in PointFun's main method that creates the point from

    ExtendedPoint pt = new ExtendedPoint();

to

    ExtendedPoint pt = new ExtendedPoint(4,1);

Recompile and execute PointFun. Record the output. What does this suggest?


 
 
 
 
 
 

Step 9. Replace the appropriate constructor in ExtendedPoint with

  /**
   * Build the point (x,y).
   */
  public ExtendedPoint(double x, double y) {
    super(x,y);
  } // ExtendedPoint(double, double)

Recompile both PointFun and ExtendedPoint. Run PointFun. If you are successful, record and explain the results. If you are not successful, record and explain the error messages.


 
 
 
 
 
 

Experiment O2.3: Adding functionality to ExtendedPoints

Required files:

Obviously, we want subclasses to do more than their superclasses do, otherwise there is no purpose to having subclasses. In particular, we often want to add new methods to subclasses. In this experiment, we will add a toString method that will convert points to printable strings.

Step 1. Make copies of Point.java, PointFun.java, and ExtendedPoint.java. If you have not already done so, update PointFun.java to use ExtendedPoints rather than Points. Compile and execute PointFun and record the results.


 
 
 
 
 
 

Step 2. Add the following toString method to ExtendedPoint.

  /**
   * Convert the point to a string for ease of printing.
   */
  public String toString() {
    return "x=" + getX() + ", y=" + getY();
  } // toString()

Recompile ExtendedPoint and PointFun. Execute PointFun. Record your results. Are they what you expected? Why or why not?


 
 
 
 
 
 

Step 3. Update the main method of PointFun so that every line that read

    out.println("(" + pt.getX() + "," + pt.getY() + ")");

now reads

    out.println(pt.toString());

Recompile and execute PointFun. Record your results. Are they what you expected? Why or why not?


 
 
 
 
 
 

Step 4. In addition to inheriting the methods of its superclass, a subclass also inherits the fields of its superclass (subject to some restrictions that you do not yet need to understand). We can see this by updating the toString method to use xcoord and ycoord rather than getX and getY.

Replace the line in toString that reads

    return "x=" + getX() + ", y=" + getY();

with one that reads

    return "X:" + this.xcoord + ",Y:" + this.ycoord;

Recompile ExtendedPoint and execute PointFun. Record your results. Are they what you expected? Why or why not?


 
 
 
 
 
 

Step 5. The previous steps suggest that we often have the choice of using the methods of the superclass (e.g., getX) to obtain the fields of the superclass (e.g., xcoord) or directly using the fields of the superclass. Which strategy do you think is better and why? You may want to consider which of the toString methods you prefer in answering this question, but you should also try to think about other issues.


 
 
 
 
 
 

Experiment O2.4: Overriding methods

Required files:

In addition to adding new methods to subclasses (as in Experiment O2.3), we may also want to change what methods do. For example, we might want to create a variant of Points that use a difference distance metrics or a variant of ExtendedPoints that print points in a different way. We will make the distance extension in this experiment and the printing extension in the next experiment.

Step 1. Make copies of Point.java, PointFun.java, and TaxicabPoint.java. Compile all three files. Execute PointFun and record the results.


 
 
 
 
 
 

Step 2. Read the source code for Point and TaxicabPoint and, in your own words, describe how TaxicabPoints differ from Points.


 
 
 
 
 
 

Step 3. Update PointFun to use TaxicabPoints instead of regular Points. Compile and execute PointFun and record your results. Are they the same as in step 1? If so, why? If not, why not?


 
 
 
 
 
 

Experiment O2.5: Overriding the toString method

Required files:

Step 1. Make copies of Point.java, PointFun.java, and ExtendedPoint.java. If you have not already done so, add the following toString method to ExtendedPoint.

  /**
   * Convert the point to a string for ease of printing.
   */
  public String toString() {
    return "x=" + getX() + ", y=" + getY();
  } // toString()

Update the main method of PointFun to use ExtendedPoints and the toString method, as in

  /**
   * Build a point and move it around.
   */
  public static void main(String[] args) {
    // We'll be generating some output.
    SimpleOutput out = new SimpleOutput();
    // The point we'll be playing with.
    ExtendedPoint pt = new ExtendedPoint(2,3);
    // Print some basic information
    out.println(pt.toString());
    out.println("  distance from origin: " + 
                pt.distanceFromOrigin());
    // Move it right a little bit.
    out.println("Shifting right by 0.7");
    pt.shiftRight(0.7);
    // Print current information
    out.println(pt.toString());
    out.println("  distance from origin: " + 
                pt.distanceFromOrigin());
    // Move it right a little bit.
    out.println("Shifting up by 2.5");
    pt.shiftUp(2.5);
    // Print current information
    out.println(pt.toString());
    out.println("  distance from origin: " + 
                pt.distanceFromOrigin());
    // Move it left a little bit.
    out.println("Shifting left by 10.2");
    pt.shiftLeft(10.2);
    // Print current information
    out.println(pt.toString());
    out.println("  distance from origin: " + 
                pt.distanceFromOrigin());
  } // main(String[])

Compile the files. Execute PointFun and record the results.


 
 
 
 
 
 

Step 2. Build a new ReextendedPoint class containing only the following lines (along with an appropriate introductory comment and constructors).

public class ReextendedPoint
  extends ExtendedPoint {
} // class ReextendedPoint

Compile the new class and correct any errors. What methods do you expect ReextendedPoint to provide?


 
 
 
 
 
 

After you've answered this question, read the notes on this step.

Step 3. Update PointFun to use ReextendedPoints instead of ExtendedPoints. Recompile and execute PointFun. Record and explain the results.


 
 
 
 
 
 

Step 4. Add the following toString method to ReextendedPoint.

  /**
   * Convert the point to a string for ease of printing.
   */
  public String toString() {
    return "(" + getX() + "," + getY() + ")";
  } // toString()

Recompile ReextendedPoint and execute PointFun. Record and explain the results.


 
 
 
 
 
 

Experiment O2.6: From Rectangle to Square

Required files:

Step 1. Make a copy of Rectangle.java. Build a subclass of Rectangle called Square. You need not put anything in Square (yet). Build a class, SquareTester that you will use for testing your Square class. The main method of SquareTester should include

    SimpleOutput out = new SimpleOutput();
    Square box = new Square();
    out.println("The area of the square is: " + box.area());

Are you able to compile all three files? If not, why not? If so, record and explain the output.


 
 
 
 
 
 

Step 2. Add a constructor to Square that takes one parameter: the length of a side. Update SquareTester to use that constructor. Compile the various components of your program and correct any errors. Enter the code for your constructor here.


 
 
 
 
 
 

Step 3. Add the following line to the main method of SquareTester. Recompile SquareTester and record the results. Explain those results.

    box.setWidth(2);
    out.println("The height of the box is now: " + box.getHeight());


 
 
 
 
 
 

Step 4. Look through the code for Rectangle. Make a list of the methods it provides. Highlight the methods that you expect to need to change but don't change any methods


 
 
 
 
 
 

Step 5. In order to correctly set the width of a square, we'll need to override the setWidth method. But we also need to access the width and height in the Rectangle class, preferably with the setWidth and setHeight of that class. How do we distinguish the two versions of setWidth? We can use super.setWidth to indicate the appropriate method of the superclass.

Write a new setWidth method that updates both width and height, which is what should happen in a square. Enter the code for that method here.


 
 
 
 
 
 


Copyright (c) 1998 Samuel A. Rebelsky. All rights reserved.

Source text last modified Tue Oct 26 11:02:31 1999.

This page generated on Tue Oct 26 15:37:02 1999 by Siteweaver.

Contact our webmaster at rebelsky@math.grin.edu