logo

APSU Notes


Polymorphism and Interfaces

Savitch 8.3-8.4

Topics

8.3 – Polymorphism

Polymorphism

  • A method is polymorphic if it can be called on different types of objects or with different parameters types.
  • Method overloading is a form of polymorphism where methods with different parameter types share the same name.
  • Inheritance makes base class methods polymorphic since they can be called on objects of a derived class.
  • Overriding inherited methods makes them behave differently when they are called on an object of a derived class.
  • Polymorphism also allows changes in a derived class method to apply to corresponding base class method.

Compile-Time and Run-Time Types

  • The compile-time type of a variable of class type is determined by the variable declaration:
1
2
Person person1; // compile-time type is Person
Person person2; // same
  • The run-time type of a variable of class type is determined when the variable is assigned a value:
1
2
person1 = new Person("Strachey, Christopher");     // run-time type is Person
person2 = new Student("Liskov, Barbara", 1171939); // run-time type is Student

Dynamic Binding and Inheritance

  • Java uses dynamic binding, so the run-time type determines which implementation of a method is used when it called.
  • Code:
1
2
3
person1.writeOutput(); // calls Person implementation
System.out.println();
person2.writeOutput(); // calls Student implementation
  • Output:
Name: Strachey, Christopher

Name: Liskov, Barbara
Student Number: 1171939

Dynamic Binding with toString

  • If a toString method is implemented in a class, an object of that class can be passed to System.out.println.
1
2
Student student = new Student("Church, Alonso", 6141903);
System.out.println(student);
  • This words because System.out.printlncalls the toString method on the Object passed a parameter.
1
2
3
public void println(Object object) {
  println(object.toString()); // calls the version that takes a String
}
  • If the Student class overrides the Objectclass implementation of toString, then the Student class implementation will be called.

8.4 – Interfaces and Abstract Classes

Java Interfaces

  • A Java interface is a program component that contains the heading for a number of public methods.
  • An interface can be declared using the keyword interface.
1
public interface Interface_Name
  • The interface contains headers for public methods, each followed by a semicolon.
1
2
3
4
5
public interface Measurable
{
  public double getPerimeter();
  public double getArea();
}

Implementing an Interface

  • A class can implement an interface by doing the following:
    1. Includes implements Interface_Namein the class definition header.
    2. Define every method declared in the interface.
  • If multiple interfaces are implemented, the interface names can be separated by commas.
  • For example, the class definition header for a Rectangle class that implements the Measurable interface would look like this:
1
public class Rectangle implements Measurable
  • The Rectangle class would need to implement the getPerimiterand getArea methods as specified in the MeasurableInterface.

The Rectangle Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Rectangle implements Measurable {
  private double myWidth;
  private double myHeight;
  public Rectangle(double width, double height) {
    myWidth = width;
    myHeight = height;
  }
  public double getPerimeter() {
    return 2 * (myWidth + myHeight);
  }
  public double getArea() {
    return myWidth * myHeight;
  }
}

An Interface as a Type

  • An interface is a reference type, so it can used as the type of a variable or parameter.
1
2
3
4
public static void display(Measurable figure) {
  System.out.println("Perimeter = " + figure.getPerimeter());
  System.out.println("Area = " + figure.getArea());
}
  • A variable with an interface type can be assigned an object of any class that implements the interface.
1
2
3
4
Measurable box = new Rectangle(5.0, 5.0);
Measurable disc = new Circle(5.0);
display(box); // calls Rectangle implementations of getPerimeter and getArea
display(disc); // calls Circle implementations of getPerimeter and getArea

The Circle Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Circle implements Measurable {
  private double myRadius;
  public Circle(double radius) {
    myRadius = radius;
  }
  public double Perimeter() {
    return 2 * Math.PI * myRadius;
  }
  public double getCircumference() { // alternate name for getPerimeter
    return getPerimeter();
  }
  public double getArea() {
    return Math.PI * myRadius * myRadius;
  }
}

Extending an Interface

  • An interface can extend one or more existing interfaces:
1
2
3
4
5
6
7
8
public interface Nameable {
  public void setName(String petName);
  public String getName();
}

public interface Callable extends Nameable {
  public void come(String petName)
}
  • A class that implements Callable must implement the two methods in Nameable as well as the one in Callable.

Case Study: Character Graphics

  • Problem: design interfaces and classes to support a program that draws shapes using text characters.
  • The program will use the following interfaces:
    • ShapeInterface: draw a shape and configure where it should be drawn.
    • RectangleInterface: set the height and width of a rectangle.
    • TriangleInterface: set the base length of the triangle.
  • The program will use the following classes:
    • ShapeBasics: a base class that implements ShapeInterface
    • Rectangle: a derived class that implements RectangleInterface
    • Triangle: a derived class that implements TriangleInterface

Character Graphics Interfaces

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface ShapeInterface {
  public void setOffset(int newOffset); // sets horizontal offset
  public int getOffset();
  public void drawAt(int lineNumber);   // draws after lineNumber blank lines
  public void drawHere();
}

public interface RectangleInterface extends ShapeInterface {
  public void set(int newHeight, int newWidth);  // adjusts the height and width
}

public interface TriangleInterface extends ShapeInterface {
  public void set(int newBase);  // adjusts the base length
}

The ShapeBasics Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class ShapeBasics implements ShapeInterface {
  private int offset;

  public ShapeBasics() {
    offset = 0;
  }

  public ShapeBasics(int theOffset) {
    offset = theOffset;
  }

  public void setOffset(int newOffset) {
    offset = newOffset;
  }

  public void getOffset() {
    return offset;
  }

  public void drawAt(int lineNumber) {
    for (int count = 0; count < lineNumber; count++)
      System.out.println();
    drawHere();
  }

  public void drawHere() {
    for (int count = 0; count < offset; count++ )
      System.out.print(' ');
    System.out.println('*');
  }
}

The Rectangle Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Rectangle extends ShapeBasics implements RectangleInterface {
  private int height;
  private int width;

  public Rectangle() {
    super();
    height = 0;
    width = 0;
  }

  public Rectangle(int theOffset, int theHeight, int theWidth) {
    super(theOffset);
    height = theHeight;
    width = theWidth;
  }

  // implements set from RectangleInterface
  public void set(int newHeight, int newWidth) {
    height = newHeight;
    width = newWidth;
  }

  // overrides drawHere from ShapeBasics
  public void drawHere() {
    drawHorizontalLine();
    drawSides();
    drawHorizontalLine();
  }

  // private methods to implement drawHere
}

The Triangle Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Triangle extends ShapeBasics implements TriangleInterface {
  private int base;

  public Triangle() {
    super();
    base = 0;
  }

  public Triangle(int theOffset, int theBase) {
    super(theOffset);
    base = theBase;
  }

  // implements set from TriangleInterface
  public void set(int newBase) {
    height = newHeight;
    width = newWidth;
  }

  // overrides drawHere from ShapeBasics
  public void drawHere() {
    drawTop();
    drawBase();
  }

  // private methods to implement drawHere
}

Case Study: The Comparable Interface

  • Java has a predefined interface called Comparable that contains header for a compareTo method.
1
public int compareTo(Object other);
  • An implementation of compareTo should return:
    • A negative number if the calling object comes before other
    • A zero if the calling object equals other
    • A positive number if the calling object comes after other
  • An array of objects that implement the Comparable interface can be passed to Array.sort, which uses compareTo for comparisons.

Defining compareTo

  • The compareTo method should handle the following cases:
    • The parameter is the same type or derived from the type of the calling object.
    • The parameter is not the same type or derived from the type of the calling object.
    • The parameter is null.
  • A compareTo method for the Person class might look like this:
1
2
3
4
5
6
7
public int compareTo(Object object) {
  if(object != null && object instanceof Person) {
    Person otherPerson = (Person)object;
    return name.compareTo(otherPerson.name);
  }
  return -1;
}

Abstract Classes

  • The ShapeBasics class was designed as a base class for other classes, not for creating objects of its own.
  • It could be reimplemented as an abstract class, which can not be instantiated and contains abstract methods that must be overridden.
1
2
3
4
5
6
7
8
9
10
public abstract class ShapeBase implements ShapeInterface {
  private int offset;
  public abstract void drawHere(); // must be overridden;
  public void drawAt(int linenumber) {
    for(int count = 0; count < lineNumber; count++)
      System.out.println();
    drawHere(); // calls derived class method
  }
  // other methods
}

Powerpoint

Quiz

Quiz 4