Download presentation
Presentation is loading. Please wait.
1
Java Programming: From the Ground Up
Chapter 13: Polymorphism
2
Polymorphism Polymorphism is the third fundamental concept of OOP.
In contrast to inheritance, polymorphism underscores the differences of class behavior in an inheritance hierarchy.
3
Ad-hoc Polymorphism – Method Overloading
The code segment overloads the constructor of a Song class. The constructor is polymorphic; the constructor has three forms. public class Song { private String composer; private String lyricist; public Song () // default constructor composer ="" ; lyricist = ""; } public Song(String name) // same person wrote words and music composer =name ; lyricist = name; public Song (String name1, String name2) // two songwriters composer =name1; lyricist = name2; // other Song methods go here Method overloading, a form of polymorphism, is also known as ad-hoc polymorphism.
4
elvis = new HoundDog();
Upcasting Upcasting in an inheritance hierarchy allows an object of a derived type to be considered an object of a base type. Dog elvis; elvis = new HoundDog(); elvis = new Beagle(); elvis = new Bassett(); Because a HoundDog is-a Dog, a HoundDog reference can be upcast to Dog (line 2). Similarly, a Beagle reference and a Bassett reference can also be considered Dog references (lines 3 and 4). The reference elvis is polymorphic, i.e., elvis has “many forms” and elvis can refer to a Dog object, a HoundDog object, a Beagle object, or a Bassett object.
5
Dynamic (or Late) Binding
A third form of polymorphism, dynamic or late binding, accentuates the behavioral differences among objects of different classes in a hierarchy. This is in contrast to inheritance, which exploits the similarities of classes.
6
The Shape Hierarchy Each class of the Shape hierarchy encapsulates a different geometrical shape. Some typical shapes are: ***** Square % %% %%% %%%% %%%%% RightTriangle # # # # # # # # # # # # # # # Triangle
7
The Shape Hierarchy Problem Statement:
Design classes Square, RightTriangle, and Triangle that encapsulate three geometrical shapes. Each class should implement a method void draw (int x, int y) that “draws” a square, a right triangle, or an equilateral triangle (a triangle with three equal sides), respectively. The parameters x and y specify the relative position of the figure: y lines down and x spaces across from the current position of the screen cursor. The instance variables of each class are: int rows, the number of rows that comprise the figure, and char character, the keyboard character used for drawing the figure.
8
The Shape Hierarchy Java Solution:
There is much the same about the three classes: the attributes are the same, and except for the draw(...) method, the getter and setter methods are the same. Factor out the commonality of the classes into one (abstract) superclass, Shape, which serves as a base class in an inheritance hierarchy that includes Square, RightTriangle, and Triangle.
9
The Shape Hierarchy The Shape hierarchy
10
The Shape Hierarchy The abstract class Shape has the following form:
public abstract class Shape { protected int rows; // figure drawn on rows rows protected char character; // the drawing character public Shape() rows = 0; char character = ' '; } public Shape(int x, char ch) rows = x; character = ch; public int getRows() return rows; public char getCharacter() return character; public void setRows(int y) rows = y; public void setCharacter(char ch) public abstract void draw(int x, int y); // must be implemented in concrete subclasses
11
The Shape Hierarchy public class Square extends Shape {
public Square() // call Shape default constructor super(); } public Square(int x, char ch) { // call Shape 2 argument constr. super(x,ch); public void draw(int x, int y) // move down y lines for ( int i = 1; i <= y; i++) System.out.println(); // for each row for (int len = 1; len<= rows;len++) { // indent x spaces for (int i = 1; i <= x; i++) System.out.print(' '); for(int j = 1; j <=rows; j++) System.out.print(character); System.out.println(); public class RightTriangle extends Shape public RightTriangle() public RightTriangle(int x, char ch) // call Shape 2 argument constr. // move down y lines for ( int i = 1; i <= y; i++) System.out.println(); // for each row for (int len = 1; len<= rows; len++) //indent x spaces for (int j = 1; j <= len; j++) System.out.print(character); public class Triangle extends Shape public Triangle () public Triangle (int x, char ch) for(int len=1; len<=rows; len++) //indent; the vertex is centered for(int i=0; i <= rows-len+x; i++) System.out.print(" "); for(int i =1; i<=len; i++) System.out.print(character +" " ); } }
12
The Shape Hierarchy Problem Statement:
Devise a test class that interactively queries a user for one of three shapes and subsequently draws the requested shape. Java Solution: The main(...) method of the following test class, requests input 1, 2, or 3 representing a square, a right triangle or an equilateral triangle, respectively. Because a Square is-a Shape, a RightTriangle is-a Shape, and a Triangle is-a Shape, all references are upcast to Shape
13
The Shape Hierarchy import java.util.*; public class TestDraw {
public static void main(String[] args) Scanner input = new Scanner(System.in); Shape shape = null; // all references can be upcast to Shape int shapeNumber; //code number for each type of figure System.out.print("Enter 1: Square, 2: RightTriangle, 3: Equilateral Triangle: "); shapeNumber = input.nextInt(); switch (shapeNumber) case 1 : shape = new Square(4,'*'); //size 4, draw with * break; case 2 : shape = new RightTriangle(5,'#'); //size 5, draw with # case 3 : shape = new Triangle(6,'+'); //size 6, draw with + default : System.out.println("Invalid entry"); // shapeNumber is not 1,2, or 3 System.exit(0); // bad data, terminate the application } shape.draw(1,1);
14
The Shape Hierarchy Discussion:
The application runs as you might expect, but only because Java implements polymorphism through late binding. On line 22, it appears that a Shape object (shape) invokes its draw(…) method. Shape is an abstract class, so no Shape object can exist. Shape does not implement draw(...) as part of the Shape class, draw(...) is declared abstract. Which draw(...) method is invoked? The reference variable shape could refer to a Square object (line 13), a RightTriangle object (line 15), or a Triangle object (line 17).
15
The Shape Hierarchy When TestDraw is compiled and translated into bytecode, the Java compiler cannot determine which draw(…) method is applicable. The compiler knows that shape refers to a kind of Shape, but it does not know which kind. The appropriate draw(...) method is not discernible until the program runs and the user chooses one of three shapes. Consequently, the compiled version of the program, i.e., the bytecode that executes on the Java Virtual Machine, does not specify which draw(...) method is appropriate. The choice of the correct draw(...) method is postponed until the program executes; that is, the choice is postponed until runtime. Polymorphism via dynamic or late binding refers to choosing the appropriate method not at compile time, but at runtime. When the TestDraw application runs, Java determines which form of draw(...) to execute.
16
How Dynamic Binding Works
The reference variable shape is declared to be of type Shape: Shape shape Shape is the apparent type or declared type of shape. A Shape object cannot be instantiated because Shape is an abstract class. The variable shape can refer to a Square object or a Triangle object, or an object of any concrete class that extends Shape.
17
How Dynamic Binding Works
The real type or actual type of a reference variable is the type of the object that is created by the new operation. The real type of shape is Square, RightTriangle, or Triangle, depending on user input. Assume that the user, TestDraw, chooses to draw a right triangle. In this case, the real type of shape is RightTriangle. When the draw(...) method is invoked by shape, Java begins searching for a fully implemented draw(...) method. The search begins in the RightTriangle class (the real type of shape). If the RightTriangle class has implemented a draw(...) method then the search ends, and that method is called. If not, then Java searches the parent of RightTriangle. Searching continues all the way up the hierarchy until an implemented draw(...) method is found (or until the Object class is reached). Java uses late binding for all method invocations except final, private, and static methods.
18
Polymorphism Makes Programs Extensible
Polymorphism allows you to generalize your classes with ease. Problem Statement: Expand the Shape class with a subclass, EmptySquare, that implements a draw method, which produces a square that is not filled. ***** * * * * * * *****
19
Polymorphism Makes Programs Extensible
Java Solution: class EmptySquare extends Shape { public EmptySquare() super(); // calls default Shape constructor } public EmptySquare(int x, char ch) super(x,ch); // call 2-argument Shape constructor public void draw(int x, int y) // move down y lines for ( int i = 1; i <= y; i++) System.out.println(); // for each row for (int len = 1; len<= rows; len++) // indent x spaces for (int i = 1; i <= x; i++) System.out.print(' '); // print a character on an edge // print spaces in the interior for(int j = 1; j <=rows; j++) if (j ==1|| j==rows || len==rows || len == 1 ) // on edge System.out.print(character); else System.out.print(" ");
20
Polymorphism and the Object class
Most horror films have tag lines – catchphrases such as “Frankenstein: A Monster Science Created - But Could Not Destroy!” Problem Statement: Design an application that stores Movie objects (a film title and a tag line) in an array, and allows Holly to search the array and retrieve a film’s tag line, given the title of the film. Java Solution: In addition to the two attributes, title and tagLine, the following Movie class: implements the standard getter and setter methods, overrides the toString() method inherited from Object so that the toString() version of the Movie class returns the title and the tag line as a String, overrides the equals(...) method inherited from Object implementing an equality that is based on the title of a film, so that two Movie objects with the same title are equal, and implements the Comparable interface by alphabetically comparing titles so that the array of Movie objects can be sorted by title.
21
Polymorphism and the Object class
Movie overrides equals(Object o) and toString(); Movie implements Comparable
22
Polymorphism and the Object class
public String toString() // overwrites toString() from Object { return "Title: "+title+" Tag line: "+ tagLine; } public void setTitle(String title) this.title = title; public String getTitle() return title; public void setTagLine(String tagLine) this. tagLine = tagLine; public String getTagLine () return tagLine; public class Movie implements Comparable { private String title; private String tagLine; public Movie() // default constructor, makes an empty Movie object title = ""; tagLine = ""; } public Movie( String name, String tag) // two-argument constructor, creates a Movie object with a title and tag line title = name; tagLine = tag; public boolean equals(Object o) // override the equals object inherited from Object // two Movie objects are equal if they have the same title return title.equals(((Movie)o).title); //notice that o must be cast to Movie public int compareTo(Object o) // implement compareTo from the Comparable interface // compareTo compares two titles. The compareTo from String is invoked return title.compareTo(((Movie)o).title); // compares two Strings
23
Polymorphism and the Object class
To locate a particular movie, the application utilizes the binary search algorithm. Binary search utilizes a sorted array. Because Movie implements the Comparable interface, an array of Movie references can be ordered. In the implementation of binary search e, the array parameter x and the key parameter are both declared of type Object. Thus, the method call, search(Object[] x, Object key) can pass arguments of any class.
24
Polymorphism and the Object class
public class Search { public static int search(Object [] x, Object key, int size) // binary search from Chapter 7 int lo = 0; int hi = size -1; int mid = (lo+hi)/2; while ( lo <= hi) if (key.equals(x[mid])) // key found return mid; else if (((Comparable)key).compareTo(x[mid]) < 0) hi = mid -1; else lo = mid + 1; mid = (lo+hi)/2; } return -1; // key not found The cast on line 13: is necessary because the parameter key refers to an Object, and Object does not implement Comparable. Without the downcast, the compiler issues a message to the effect that the name compareTo is unknown.
25
Polymorphism and the Object class
public void searchFilm() { // Prompt user for a movie title // Search the array for the film with that title // If the film is in the array, print the title and tagline // If the film is not in the array, issue a message System.out.println(); Movie key = new Movie(); // an empty Movie object int place; // a position in the array System.out.println("Input a title. Hit Enter to end"); do { //get title from user System.out.print("\nTitle: "); title = input.nextLine(); if (title.equals("")) break; // end if user hits 'Enter' key.setTitle(title); // wrap title in a Movie object key.setTagLine(""); //the tagline is empty at this point // invoke binary search to find a movie object with the title as key // if successful, place contains the position in the array; otherwise // place contains -1 place = Search.search(movies, key, num); // key is a Movie object if (place >= 0 && place < num) // successful search System.out.println(movies[place]); // print the object at place else System.out.println(title +" not found"); } while(true); } public static void main(String[] args) throws IOException MovieSearch movieSearch = new MovieSearch(); import java.util.Scanner; import java.io.*; public class MovieSearch { Scanner input = new Scanner(System.in); private String title, tagLine; private Movie[] movies ; private final int MAX_MOVIES = 500; private int num; // the total number of films in the file public MovieSearch() throws IOException num = 0; movies = new Movie[MAX_MOVIES]; File inputFile = new File("movielines.txt"); if( !inputFile.exists()) System.out.println("File movielines.txt not found "); System.exit(0); } Scanner input = new Scanner(inputFile); String line; // to hold one full line from the file while (input.hasNext()) // while there is more data String name = input.nextLine(); // advance to next line, returns all “skipped” data String tag = input.nextLine(); movies[num] = new Movie (name, tag); num++; input.close(); SelectionSort.sort(movies, num); // the array must be kept sorted to utilize binary search System.out.println("\n"+ num +" titles entered"); System.out.println(" \n"); searchFilm();
26
The Movie Class Discussion The Movie Class:
On line 21 of the Movie class return title.equals(((Movie)x).title); the equals(...) method invoked on line 21 is called by title, which is a String. The String class overrides equals(Object). So the call title.equals(((Movie)x).title); compares two String objects via String's version of equals(...), i.e., by comparing the characters in each String. The cast of x to Movie is necessary because the apparent type of x is Object and Objects do not have title attributes.
27
Similarly, the statement
return title.compareTo(((Movie)x).title); invokes the compareTo(...) method of the String class. The remainder of the Movie class is straightforward and should present no difficulty.
28
The Search Class The Search Class: On line 11 of the Search class,
if (key.equals(x[mid])) the key object is compared to x[mid] via equals(...). This is the equals(...) method inherited from Object. If this equals(...) method is not overridden in Movie, then references are compared, and the result is incorrect. Similarly, on line 13, else if (((Comparable)key).compareTo(x[mid]) < 0) the compareTo(...) method is invoked by key. Accordingly, Movie implements the Comparable interface.
29
The MovieSearch Class The MovieSearch Class:
The statements on lines continually perform the following actions: read a title and tagline from the text file, movielines.txt, instantiate a Movie object with the two-argument constructor, and store a reference to the Movie object in the array movies, until all data has been read from movielines.txt.
30
The MovieSearch Class The searchFilm() method repeatedly
creates an empty Movie object, key (line 42), queries a user for the title of a movie, sets the title attribute of key appropriately and sets the tagline field to the empty string passes key to search(...), which returns the index of key in the array movies, and processes the returned information from search(...): If key is not found, search(...) returns –1. If key is found, the film and tagline are displayed, otherwise a “title not found” message is issued. until a user presses “Enter” without supplying a movie title.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.