View
14
Download
0
Category
Preview:
Citation preview
Chapter 13
Inheritance and Polymorphism
CS 180Sunil PrabhakarDepartment of Computer Science Purdue University
2
Introduction
Inheritance and polymorphism are key concepts of Object Oriented Programming.
Inheritance facilitates the reuse of code. A subclass inherits members (data and methods)
from all its ancestor classes. The subclass can add more functionality to the
class or replace some functionality that it inherits. Polymorphism simplifies code by automatically
using the appropriate method for a given object. Polymorphism also makes it easy to extend code.
3
Inheritance A superclass corresponds to a general class, and
a subclass is a specialization of the superclass. E.g. Account, Checking, Savings.
Behavior and data common to the subclasses is often available in the superclass. E.g. Account number, owner name, data opened.
Each subclass provides behavior and data that is relevant only to the subclass. E.g. Minimum balance for checking a/c, interest rate
and computation for savings account. The common behavior is implemented once in
the superclass and automatically inherited by the subclasses.
4
Defining Classes with Inheritance
Case Study: Suppose we want implement a class roster that
contains both undergraduate and graduate students. Each student’s record will contain his or her name,
three test scores, and the final course grade. The formula for determining the course grade is
different for graduate students than for undergraduate students.
5
Modeling Two Types of Students
There are two ways to design the classes to model undergraduate and graduate students. We can define two unrelated classes, one for
undergraduates and one for graduates. We can model the two kinds of students by using
classes that are related in an inheritance hierarchy. Two classes are unrelated if they are not
connected in an inheritance relationship. NOTE: all classes inherit from Object
6
Classes for the Class Roster
For the Class Roster sample, we design three classes: Student UndergraduateStudent GraduateStudent
The Student class will incorporate behavior and data common to both UndergraduateStudent and GraduateStudent objects.
The UndergraduateStudent class and the GraduateStudent class will each contain behaviors and data specific to their respective objects.
7
Creating a subclass
We use the keyword extends in the class header to declare that it is a subclass:public class GraduateStudent extends Student {
Student is the superclass, parent, or base class. A parent (of a parent …) is an ancestor class.
GraduateStudent is the subclass, child, or derived class. A child (of a child ...) is a descendent class.
If a class does have the extend keyword, then it derives from the Object class.
8
Example: Studentclass Student { protected final static int NUM_OF_TESTS = 3; protected String name; protected int[] test; protected String courseGrade;
public Student( ) { this("No Name"); } public Student(String studentName) { name = studentName; test = new int[NUM_OF_TESTS]; courseGrade = "****"; } public String getCourseGrade( ) { return courseGrade; } public String getName( ) { return name; } public int getTestScore(int testNumber) { return test[testNumber-1]; } public void setName(String newName) { name = newName; } public void setTestScore(int testNumber, int testScore) { test[testNumber-1] = testScore; } public void computeCourseGrade();
}
9
Example: GraduateStudent
class GraduateStudent extends Student{
public void computeCourseGrade() { int total = 0;
for (int i = 0; i < NUM_OF_TESTS; i++) { total += test[i]; }
if (total / NUM_OF_TESTS >= 80) { courseGrade = "Pass"; } else { courseGrade = "No Pass"; } }}
10
Example: UndergraduateStudent
class UndergraduateStudent extends Student{
public void computeCourseGrade() { int total = 0;
for (int i = 0; i < NUM_OF_TESTS; i++) { total += test[i]; }
if (total / NUM_OF_TESTS >= 70) { courseGrade = "Pass"; } else { courseGrade = "No Pass"; } }}
11
Inheritance Hierarchy
+ NUM_OF_TESTS# name# test# courseGrade
Student
+ Student(): void+ Student(String): void+ getCourseGrade(): String+ getName(): String+ getTestScore(int): int+ setName(String): void+ setTestScore(int, int): void
UndergraduateStudent
+ computeCourseGrade(): void
GraduateStudent
+ computeCourseGrade(): void
New visibility modifier: #protected
12
Overriding All non-private members of a class are inherited by
derived classes This includes instance and class members
A derived class may however, override an inherited method Data members can also be overridden but should be avoided
since it only creates confusion. To override a method, the derived class simply defines a
method with the same name, number and types of parameters (same signature) An overridden method cannot change the return type!
A subclass may overload any method (inherited or otherwise) by using the same name, but different signature.
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
overloaded
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
overridden
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
inherited
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
overridden & overloaded
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
Overloaded & Auto cast
13
Overriding and overloadingSup
Sub
methodA(){}methodA(int i){}
methodA(){}methodA(char c){}
Sup sup = new Sup(); Sub sub = new Sub(); int i=9; char c = 'c';
sup.methodA();
sup.methodA(i);
sub.methodA();
sub.methodA(i);
sub.methodA(c);
sup.methodA(c);
14
Limiting inheritance and overriding
If a class is declared to be final, then no other classes can derive from it.
public final class ClassA
If a method is declared to be final, then no derived class can override this method. A final method can be overloaded in a derived
class though.public final void methodA()
15
The protected Modifier
The modifier protected makes a data member or method visible and accessible only to instances of the class and descendant classes.
public data members and methods are accessible to everyone.
private data members and methods are accessible only to instances of the class.
protected is similar to: public for descendant classes private for any other class
16
Inheritance and Member Accessibility We use the following visual representation of
inheritance to illustrate data member accessibility.
publicprotectedprivate
Accessible Inaccessible
16
Inheritance and Member Accessibility We use the following visual representation of
inheritance to illustrate data member accessibility.
publicprotectedprivate
Super
Sub
Class Hierarchy
Accessible Inaccessible
16
Inheritance and Member Accessibility We use the following visual representation of
inheritance to illustrate data member accessibility.
publicprotectedprivate
Super
Sub
Class Hierarchy
:Super
:Sub:Super
Instances
This shows the inheritedcomponents of the superclass are part ofthe subclass instance
Accessible Inaccessible
17
:Super
:Sub:Super
Accessible Inaccessible
The Effect of the Visibility Modifiers
:Client
Accessibility froma Client method
publicprotectedprivate
17
:Super
:Sub:Super
Accessible Inaccessible
The Effect of the Visibility Modifiers
:Client
Only public members, those definedfor the class and those inherited, arevisible from outside. All else is hidden from the outside.
Accessibility froma Client method
publicprotectedprivate
17
:Super
:Sub:Super
Accessible Inaccessible
The Effect of the Visibility Modifiers
:Client
Only public members, those definedfor the class and those inherited, arevisible from outside. All else is hidden from the outside.
Accessibility froma Client method
publicprotectedprivate
17
:Super
:Sub:Super
Accessible Inaccessible
The Effect of the Visibility Modifiers
:Client
Only public members, those definedfor the class and those inherited, arevisible from outside. All else is hidden from the outside.
Accessibility froma Client method
publicprotectedprivate
17
:Super
:Sub:Super
Accessible Inaccessible
The Effect of the Visibility Modifiers
:Client
Only public members, those definedfor the class and those inherited, arevisible from outside. All else is hidden from the outside.
Accessibility froma Client method
publicprotectedprivate
17
:Super
:Sub:Super
Accessible Inaccessible
The Effect of the Visibility Modifiers
:Client
Only public members, those definedfor the class and those inherited, arevisible from outside. All else is hidden from the outside.
Accessibility froma Client method
publicprotectedprivate
18
Accessibility of Super from Sub
:Sub:SuperAccessibility from a method
of the Sub class
publicprotectedprivate
18
Accessibility of Super from Sub
:Sub:SuperAccessibility from a method
of the Sub class
From a method of the Sub, everything is visible except the private members of its super class.
publicprotectedprivate
18
Accessibility of Super from Sub
:Sub:SuperAccessibility from a method
of the Sub class
From a method of the Sub, everything is visible except the private members of its super class.
publicprotectedprivate
18
Accessibility of Super from Sub
:Sub:Super
Accessibility from a method of the Sub class
From a method of the Sub, everything is visible except the private members of its super class.
publicprotectedprivate
19
Accessibility from Another Instance
Data members accessible from an instance are also accessible from other instances of the same class.
one:ClassA two:ClassAThis could be private,Protected, or public.
20
Inheritance and Constructors Unlike members of a superclass, constructors of a
superclass are not inherited by its subclasses. As always, each class that does not define a
constructor is automatically given a default constructor.
In addition, in each constructor of a derived class, we must make a call to the constructor of the base class by calling: super(); This must be the first statement in the constructor.
If this statement is not present, the compiler automatically adds it as the first statement.
You may optionally call some other constructor of the base class, e.g.: super( “some string” );
21
Constructors and inheritance
The constructor for each class can be used to initialize the variables defined in that class.
For all classes, calls to the constructors are chained all the way back to the constructor for the Object class.
Recall that it is also possible to call another constructor of the same class using the this keyword.
However, this must also be the first statement of the constructor!
A constructor cannot call another constructor of the same class and the base class.
22
ConstructorsSup
public Sup(){}public Sup(int i){}
Subpublic Sub(){ this(‘x’);}public Sub(char c){ …}public Sub(int i){ super(i); …}
22
ConstructorsSup
public Sup(){}public Sup(int i){}
Subpublic Sub(){ this(‘x’);}public Sub(char c){ …}public Sub(int i){ super(i); …}
Subpublic Sub(){ this(‘x’);}public Sub(char c){ super(); …}public Sub(int i){ super(i); …}
Sup
public Sup(){ super();}public Sup(int i){ super();}
Addedby thecompiler
22
ConstructorsSup
public Sup(){}public Sup(int i){}
Subpublic Sub(){ this(‘x’);}public Sub(char c){ …}public Sub(int i){ super(i); …}
Sup sup1, sup2;Sub sub1, sub2, sub3;
sup1 = new Sup();sup2 = new Sup(7);
sub1 = new Sub();sub2 = new Sub(‘y’);sub3 = new Sub(5);
Subpublic Sub(){ this(‘x’);}public Sub(char c){ super(); …}public Sub(int i){ super(i); …}
Sup
public Sup(){ super();}public Sup(int i){ super();}
Addedby thecompiler
23
Super keyword
The super keyword is a call to the constructor of the parent class.
It can also be used to call a method of the parent class:
super.methodA(); This can be useful to call an overridden method. Similarly, it can be used to access data members
of the parent.
24
super keyword example.
Sup
methodA(){}methodA(int i){}
Sub
methodA(){}methodB(){ methodA(); this.methodA(); super.methodA(); methodA(7); methodA(‘x’);}
24
super keyword example.
Sup
methodA(){}methodA(int i){}
Sub
methodA(){}methodB(){ methodA(); this.methodA(); super.methodA(); methodA(7); methodA(‘x’);}
24
super keyword example.
Sup
methodA(){}methodA(int i){}
Sub
methodA(){}methodB(){ methodA(); this.methodA(); super.methodA(); methodA(7); methodA(‘x’);}
24
super keyword example.
Sup
methodA(){}methodA(int i){}
Sub
methodA(){}methodB(){ methodA(); this.methodA(); super.methodA(); methodA(7); methodA(‘x’);}
24
super keyword example.
Sup
methodA(){}methodA(int i){}
Sub
methodA(){}methodB(){ methodA(); this.methodA(); super.methodA(); methodA(7); methodA(‘x’);}
24
super keyword example.
Sup
methodA(){}methodA(int i){}
Sub
methodA(){}methodB(){ methodA(); this.methodA(); super.methodA(); methodA(7); methodA(‘x’);}
25
Polymorphism
Polymorphism allows a single variable to refer to objects from different subclasses in the same inheritance hierarchy
For example, if Cat and Dog are subclasses of Pet, then the following statements are valid:
25
Polymorphism
Polymorphism allows a single variable to refer to objects from different subclasses in the same inheritance hierarchy
For example, if Cat and Dog are subclasses of Pet, then the following statements are valid:
Pet myPet;
myPet = new Dog();
. . .
myPet = new Cat();
26
Creating the roster Array
We can maintain our class roster using an array, combining objects from the Student, UndergraduateStudent, and GraduateStudent classes.
Student roster = new Student[40];
. . .
roster[0] = new GraduateStudent();
roster[1] = new UndergraduateStudent();
roster[2] = new UndergraduateStudent();
. . .
27
State of the roster Array
The roster array with elements referring to instances of GraduateStudent or UndergraduateStudent classes.
27
State of the roster Array
The roster array with elements referring to instances of GraduateStudent or UndergraduateStudent classes.
28
Sample Polymorphic Message To compute the course grade using the roster
array, we execute
28
Sample Polymorphic Message To compute the course grade using the roster
array, we executefor (int i = 0; i < numberOfStudents; i++) {
roster[i].computeCourseGrade();
}
• If roster[i] refers to a GraduateStudent, then the computeCourseGrade method of the GraduateStudent class is executed.
• If roster[i] refers to an UndergraduateStudent, then the computeCourseGrade method of the UndergraduateStudent class is executed.
29
Dynamic Binding
At compile time, it is not known which version of a polymorphic method will get executed This is determined at run-time depending upon
the class of the object This is called dynamic (late) binding Each object of a subclass is also an object
of the superclass. But not vice versa! Do not confuse dynamic binding with
overloaded methods.
30
Object Type
Consider the inheritance hierarchy: Object ← A ← B An object of class B is also an object of classes A
and Object. Thus we can use objects of class B wherever we
can use objects of class A. The reverse is not true. A reference of type A can refer to an object of
type B. However if we want to access the functionality of B on that object, we have to type cast to type B before doing that.
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
sub
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
:Sub
sub
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
:Sub
sub
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
:Sub
sub
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
:Sub
sub
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
:Sub
sub
sup
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
:Sub
sub
sup
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
:Sub
sub
sup
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
:Sub
sub
sup
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
:Sub
sub
sup
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
:Sub
sub
sup
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
:Sub
sub
sup
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
:Sub
sub
sup
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
:Sub
sub
sup
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
:Sub
sub
sup
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
Note: sup.methodB( )will not compile.
:Sub
sub
sup
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
Note: sup.methodB( )will not compile.
:Sub
sub
sup
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
Note: sup.methodB( )will not compile.
:Sub
sub
sup
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
Note: sup.methodB( )will not compile.
:Sub
sub
sup
sub1
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
Note: sup.methodB( )will not compile.
:Sub
sub
sup
sub1
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
Note: sup.methodB( )will not compile.
Casting to Sub will work,but a runtime exception
(ClassCastException) will be thrown if the object
is not really a Sub object.
:Sub
sub
sup
sub1
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
Note: sup.methodB( )will not compile.
Casting to Sub will work,but a runtime exception
(ClassCastException) will be thrown if the object
is not really a Sub object.
:Sub
sub
sup
sub1
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
Note: sup.methodB( )will not compile.
Casting to Sub will work,but a runtime exception
(ClassCastException) will be thrown if the object
is not really a Sub object.
:Sub
sub
sup
sub1
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
Note: sup.methodB( )will not compile.
Casting to Sub will work,but a runtime exception
(ClassCastException) will be thrown if the object
is not really a Sub object.
:Sub
sub
sup
sub1
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
Note: sup.methodB( )will not compile.
Casting to Sub will work,but a runtime exception
(ClassCastException) will be thrown if the object
is not really a Sub object.
:Sub
sub
sup
sub1
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
Note: sup.methodB( )will not compile.
Casting to Sub will work,but a runtime exception
(ClassCastException) will be thrown if the object
is not really a Sub object.
:Sub
sub
sup
sub1
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
Note: sup.methodB( )will not compile.
Casting to Sub will work,but a runtime exception
(ClassCastException) will be thrown if the object
is not really a Sub object.
:Sub
sub
sup
sub1
31
Polymorphism exampleSup
methodA(){}
SubmethodA(){}methodB(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodB(); Sub sub1 = (Sub)sup; sub1.methodA(); sub1.methodB();
Note: sup.methodB( )will not compile.
Casting to Sub will work,but a runtime exception
(ClassCastException) will be thrown if the object
is not really a Sub object.
:Sub
sub
sup
sub1
32
ExampleSup
Sub
methodA(){}methodA(String[] s){}
methodA(int i){}methodA(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodA(); sub = (Sub)sup; sub.methodA(); sub.methodA(“test”);
32
ExampleSup
Sub
methodA(){}methodA(String[] s){}
methodA(int i){}methodA(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodA(); sub = (Sub)sup; sub.methodA(); sub.methodA(“test”);
32
ExampleSup
Sub
methodA(){}methodA(String[] s){}
methodA(int i){}methodA(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodA(); sub = (Sub)sup; sub.methodA(); sub.methodA(“test”);
32
ExampleSup
Sub
methodA(){}methodA(String[] s){}
methodA(int i){}methodA(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodA(); sub = (Sub)sup; sub.methodA(); sub.methodA(“test”);
32
ExampleSup
Sub
methodA(){}methodA(String[] s){}
methodA(int i){}methodA(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodA(); sub = (Sub)sup; sub.methodA(); sub.methodA(“test”);
32
ExampleSup
Sub
methodA(){}methodA(String[] s){}
methodA(int i){}methodA(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodA(); sub = (Sub)sup; sub.methodA(); sub.methodA(“test”);
32
ExampleSup
Sub
methodA(){}methodA(String[] s){}
methodA(int i){}methodA(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodA(); sub = (Sub)sup; sub.methodA(); sub.methodA(“test”);
32
ExampleSup
Sub
methodA(){}methodA(String[] s){}
methodA(int i){}methodA(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodA(); sub = (Sub)sup; sub.methodA(); sub.methodA(“test”);
32
ExampleSup
Sub
methodA(){}methodA(String[] s){}
methodA(int i){}methodA(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodA(); sub = (Sub)sup; sub.methodA(); sub.methodA(“test”);
32
ExampleSup
Sub
methodA(){}methodA(String[] s){}
methodA(int i){}methodA(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodA(); sub = (Sub)sup; sub.methodA(); sub.methodA(“test”);
32
ExampleSup
Sub
methodA(){}methodA(String[] s){}
methodA(int i){}methodA(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodA(); sub = (Sub)sup; sub.methodA(); sub.methodA(“test”);
32
ExampleSup
Sub
methodA(){}methodA(String[] s){}
methodA(int i){}methodA(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodA(); sub = (Sub)sup; sub.methodA(); sub.methodA(“test”);
32
ExampleSup
Sub
methodA(){}methodA(String[] s){}
methodA(int i){}methodA(){}
Sub sub = new Sub();Sup sup;
sup = sub; sup.methodA(); ((Sub)sup).methodA(); sub = (Sub)sup; sub.methodA(); sub.methodA(“test”);
33
The instanceof Operator
The instanceof operator can help us discover the class of an object at runtime.
The following code counts the number of undergraduate students.
new undergradCount = 0;
for (int i = 0; i < numberOfStudents; i++) {
if ( roster[i] instanceof UndergraduateStudent ) {
undergradCount++;
}
}
34
Abstract Superclasses and Methods
When we define a superclass, we often do not need to create any instances of the superclass.
Depending on whether we need to create instances of the superclass, we must define the class differently.
We will study examples based on the Student superclass defined earlier.
35
Definition: Abstract Class An abstract class is a class
defined with the modifier abstract OR that contains an abstract method OR that does not provide an implementation of an inherited abstract
method
An abstract method is a method with the keyword abstract, and it ends with a semicolon instead of a method body. Private methods and static methods may not be declared
abstract.
No instances can be created from an abstract class.
36
Case 1
A Student must be Undergraduate or Graduate
If a student must be either an undergraduate or a graduate student, we only need instances of UndergraduateStudent or GraduateStudent.
Therefore, we should define the Student class so that no instances may be created of it.
37
Example: Abstract classesabstract class Student {
protected final static int NUM_OF_TESTS = 3; protected String name; protected int[] test; protected String courseGrade;
public Student( ) { this("No Name"); } public Student(String studentName) { name = studentName; test = new int[NUM_OF_TESTS]; courseGrade = "****"; } public String getCourseGrade( ) { return courseGrade; } public String getName( ) { return name; } public int getTestScore(int testNumber) { return test[testNumber-1]; } public void setName(String newName) { name = newName; } public void setTestScore(int testNumber, int testScore) { test[testNumber-1] = testScore; }}
37
Example: Abstract classesabstract class Student {
protected final static int NUM_OF_TESTS = 3; protected String name; protected int[] test; protected String courseGrade;
public Student( ) { this("No Name"); } public Student(String studentName) { name = studentName; test = new int[NUM_OF_TESTS]; courseGrade = "****"; } public String getCourseGrade( ) { return courseGrade; } public String getName( ) { return name; } public int getTestScore(int testNumber) { return test[testNumber-1]; } public void setName(String newName) { name = newName; } public void setTestScore(int testNumber, int testScore) { test[testNumber-1] = testScore; }}
class UndergraduateStudent extends Student { public void computeCourseGrade() { int total = 0; for (int i = 0; i < NUM_OF_TESTS; i++) { total += test[i]; } if (total / NUM_OF_TESTS >= 70) { courseGrade = "Pass"; } else { courseGrade = "No Pass"; } }}
37
Example: Abstract classesabstract class Student {
protected final static int NUM_OF_TESTS = 3; protected String name; protected int[] test; protected String courseGrade;
public Student( ) { this("No Name"); } public Student(String studentName) { name = studentName; test = new int[NUM_OF_TESTS]; courseGrade = "****"; } public String getCourseGrade( ) { return courseGrade; } public String getName( ) { return name; } public int getTestScore(int testNumber) { return test[testNumber-1]; } public void setName(String newName) { name = newName; } public void setTestScore(int testNumber, int testScore) { test[testNumber-1] = testScore; }}
class UndergraduateStudent extends Student { public void computeCourseGrade() { int total = 0; for (int i = 0; i < NUM_OF_TESTS; i++) { total += test[i]; } if (total / NUM_OF_TESTS >= 70) { courseGrade = "Pass"; } else { courseGrade = "No Pass"; } }}
class GraduateStudent extends Student { public void computeCourseGrade() { int total = 0; for (int i = 0; i < NUM_OF_TESTS; i++) { total += test[i]; } if (total / NUM_OF_TESTS >= 80) { courseGrade = "Pass"; } else { courseGrade = "No Pass"; } }}
38
Abstract example (contd.) Non-private members of the abstract parent class are inherited. Note: constructors are not inherited! Default constructor calls super!
public class Test {
public static void main(String[ ] args){ Student s; GraduateStudent g; UndergraduateStudent u;
s = new Student(); g = new GraduateStudent(“John”); g = new GraduateStudent(); u = new UndergraduateStudent();
System.out.println(g.getName()); System.out.println(u.getName()); }
}
38
Abstract example (contd.) Non-private members of the abstract parent class are inherited. Note: constructors are not inherited! Default constructor calls super!
public class Test {
public static void main(String[ ] args){ Student s; GraduateStudent g; UndergraduateStudent u;
s = new Student(); g = new GraduateStudent(“John”); g = new GraduateStudent(); u = new UndergraduateStudent();
System.out.println(g.getName()); System.out.println(u.getName()); }
}
Cannot instantiateabstract class.
38
Abstract example (contd.) Non-private members of the abstract parent class are inherited. Note: constructors are not inherited! Default constructor calls super!
public class Test {
public static void main(String[ ] args){ Student s; GraduateStudent g; UndergraduateStudent u;
s = new Student(); g = new GraduateStudent(“John”); g = new GraduateStudent(); u = new UndergraduateStudent();
System.out.println(g.getName()); System.out.println(u.getName()); }
}
Cannot instantiateabstract class.
Error: constructor not inherited!
38
Abstract example (contd.) Non-private members of the abstract parent class are inherited. Note: constructors are not inherited! Default constructor calls super!
public class Test {
public static void main(String[ ] args){ Student s; GraduateStudent g; UndergraduateStudent u;
s = new Student(); g = new GraduateStudent(“John”); g = new GraduateStudent(); u = new UndergraduateStudent();
System.out.println(g.getName()); System.out.println(u.getName()); }
}
Cannot instantiateabstract class.
Error: constructor not inherited!
Inherited from abstractparent class.
39
Case 2
Student does not have to be Undergraduate or Graduate.
In this case, we may design the Student class in one of two ways. We can make the Student class instantiable. We can leave the Student class abstract and
add a third subclass, OtherStudent, to handle a student who does not fall into the UndergraduateStudent or GraduateStudent categories.
40
Which Approach to Use?
The best approach depends on the particular situation.
When considering design options, we can ask ourselves which approach allows easier modification and extension.
41
Inheritance versus Interface
The Java interface is used to share common behavior (only method headers) among the instances of different classes.
Inheritance is used to share common code (including both data members and methods) among the instances of related classes.
In your program designs, remember to use the Java interface to share common behavior. Use inheritance to share common code.
If an entity A is a specialized form of another entity B, then model them using inheritance. Declare A as a subclass of B.
42
Interface vs inheritance
An interface essentially provides compliance with some desired behavior.
Inheritance allows sharing of code.
Interface Inheritance
Data members? No YesMethods? Only headers -- no
bodyYes
Keyword implements extendsMultiple? Yes NoInstantiable? No Yes (if not abstract)
Interfaces
A class does not extend an interface, instead it implements an interface.
Implementing implies that the class must provide the bodies for all the methods specified in the interface i.e. with the same signatures & return types
Remember: GUI interfaces ActionListener
43
44
Introduction to Data Structures
A data structure is a specific organization of data for efficiency or ease of coding. E.g. an array allows us to manage a large
number of similar items. Many different types of data structures are
used in programming. CS251 deals only with this topic! We will look at two example data structures
Linked list Queue
45
Linked List
Recall that an array’s capacity is fixed once it is created or initialized.
The LinkedList class in java.util used a linked list to implement a variable size list of objects.
How does this work? We will study it by creating our own version
of the LinkedList class which can store a list of objects of any class, in order.
46
Objective
The linked list will allow us to Create an empty list. Add items to the end of the list. Delete items from the end of the list. Iterate through the list from beginning to end.
Note: no position indexing in this version. Our linked list will be implemented as a chain of
Node objects. Each Node object will have
An Object data member that is the value stored at that position.
A reference to the next node in the list.
47
The Node Classclass Node { private Node next; private Object content;
public void Node() { next = null; content = null; } public Object getContent(){ return content; } public void setContent(Object c){ content = c; } public Node getNext(){ return next; } public void setNext(Node nextNode){ next = nextNode; }}
:Nodenext
content
48
The LinkedList classclass LinkedList { private Node head; private Node iterator;
public void LinkedList() { head = null; iterator = null; } public void addToHead(Object c){ Node n = new Node(); n.setContent(c); n.setNext(head); head = n; } public void deleteFromHead throws Exception (){ if(head== null) throw new Exception(“Empty List”); else head = head.getNext(); } public void getFromHead throws Exception (){ if(head== null) throw new Exception(“Empty List”); else return head.getContent(); }
public void startScan throws Exception (){ if(head == null) throw new Exception(“Empty List”); else iterator = head; } public boolean hasMore(){ if(iterator.next == null) return false; else return true; } public void moveAhead(){ iterator = iterator.getNext(); }
public Object getCurrentItem throws Exception (){ if(iterator == null) throw new Exception(“No Current Item”); return iterator.getContent(); }}
49
Example
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
49
Example
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
49
Example
:LinkedListhead
iterator
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
49
Example
:LinkedListhead
iterator
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
s
49
Example
:LinkedListhead
iterator
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
“test1”
s
49
Example
:LinkedListhead
iterator
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
:Node
content
next
“test1”
s
49
Example
:LinkedListhead
iterator
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
:Node
content
next
“test1”
s
50
Example
:LinkedListhead
iterator
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
:Node
content
next
“test1”
s
50
Example
:LinkedListhead
iterator
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
:Node
content
next
“test1”
s“test2”
50
Example
:LinkedListhead
iterator
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
:Node
content
next
“test1”
s“test2”
50
Example
:LinkedListhead
iterator
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
:Node
content
next
“test1”
s“test2”
:Node
content
next
50
Example
:LinkedListhead
iterator
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
:Node
content
next
“test1”
s“test2”
:Node
content
next
51
Example
:LinkedListhead
iterator
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
:Node
content
next
“test1”
s“test2”
:Node
content
next
51
Example
:LinkedListhead
iterator
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
:Node
content
next
“test1”
s“test2”
:Node
content
next
“test3”
51
Example
:LinkedListhead
iterator
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
:Node
content
next
“test1”
s“test2”
:Node
content
next
“test3”
51
Example
:LinkedListhead
iterator
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
:Node
content
next
“test1”
s“test2”
:Node
content
next
“test3”
:Node
content
next
51
Example
:LinkedListhead
iterator
LinkedList list;
list = new LinkedList();
String s;
s = “test1”;
List.addToHead(s);
s = “test2”;
list.addToHead(s);
s = “test3”;
list.addToHead(s);
list
:Node
content
next
“test1”
s“test2”
:Node
content
next
“test3”
:Node
content
next
52
Example
:LinkedListhead
iterator
list
:Node
content
next
“test1”
s“test2”
:Node
content
next
“test3”
:Node
content
next
…list.startScan();s = (String)
list.getCurrentItem();System.out.println(s);while(list.hasMore()){ list.moveAhead(); s = (String)
list.getCurrentItem(); System.out.println(s);}
52
Example
:LinkedListhead
iterator
list
:Node
content
next
“test1”
s“test2”
:Node
content
next
“test3”
:Node
content
next
…list.startScan();s = (String)
list.getCurrentItem();System.out.println(s);while(list.hasMore()){ list.moveAhead(); s = (String)
list.getCurrentItem(); System.out.println(s);}
52
Example
:LinkedListhead
iterator
list
:Node
content
next
“test1”
s“test2”
:Node
content
next
“test3”
:Node
content
next
…list.startScan();s = (String)
list.getCurrentItem();System.out.println(s);while(list.hasMore()){ list.moveAhead(); s = (String)
list.getCurrentItem(); System.out.println(s);}
52
Example
:LinkedListhead
iterator
list
:Node
content
next
“test1”
s“test2”
:Node
content
next
“test3”
:Node
content
next
…list.startScan();s = (String)
list.getCurrentItem();System.out.println(s);while(list.hasMore()){ list.moveAhead(); s = (String)
list.getCurrentItem(); System.out.println(s);}
52
Example
:LinkedListhead
iterator
list
:Node
content
next
“test1”
s“test2”
:Node
content
next
“test3”
:Node
content
next
…list.startScan();s = (String)
list.getCurrentItem();System.out.println(s);while(list.hasMore()){ list.moveAhead(); s = (String)
list.getCurrentItem(); System.out.println(s);}
52
Example
:LinkedListhead
iterator
list
:Node
content
next
“test1”
s“test2”
:Node
content
next
“test3”
:Node
content
next
…list.startScan();s = (String)
list.getCurrentItem();System.out.println(s);while(list.hasMore()){ list.moveAhead(); s = (String)
list.getCurrentItem(); System.out.println(s);}
52
Example
:LinkedListhead
iterator
list
:Node
content
next
“test1”
s“test2”
:Node
content
next
“test3”
:Node
content
next
…list.startScan();s = (String)
list.getCurrentItem();System.out.println(s);while(list.hasMore()){ list.moveAhead(); s = (String)
list.getCurrentItem(); System.out.println(s);}
53
Example
:LinkedListhead
iterator
list
:Node
content
next
“test1”
“test2”
:Node
content
next
“test3”
:Node
content
next
…list.deleteFromHead();
53
Example
:LinkedListhead
iterator
list
:Node
content
next
“test1”
“test2”
:Node
content
next
“test3”
:Node
content
next
…list.deleteFromHead();
53
Example
:LinkedListhead
iterator
list
:Node
content
next
“test1”
“test2”
:Node
content
next
“test3”
…list.deleteFromHead();
53
Example
:LinkedListhead
iterator
list
:Node
content
next
“test1”
“test2”
:Node
content
next
…list.deleteFromHead();
54
Queue
A similar Node class can be used to implement another data structure called a First-In-First-out (FIFO) queue.
A FIFO queue is often used by operating systems for processes, requests, etc.
In a FIFO queue, items are added at one end and deleted from the other end.
For this we need to have pointers going in both directions: Node2
55
The Node2 Classclass Node2 {
private Node2 next, prev;
private Object content;
public void Node2() {
next = null;
prev = null;
content = null;
} public Object getContent(){ return content; } public void setContent(Object c){ content = c; } public Node2 getNext(){ return next; } public void setNext(Node2 nextNode){ next = nextNode; } public Node getPrev(){ return prev; } public void setPrev(Node2 prevNode){ prev = prevNode; }}
:Node2next
content
prev
56
The FifoQ classclass FifoQ {
private Node2 head, tail;
public void FifoQ() {
head = null;
tail = null;
} public void addToQ(Object c){ Node2 n = new Node2(); n.setContent(c); n.setNext(head); head.setPrev(n); head = n; } public void deleteFromQ throws Exception (){ if(tail== null) throw new Exception(“Empty Queue”); if(tail.getPrev() == null){ tail = null; head = null; } else { tail = tail.getPrev(); tail.setNext(null); } }
57
Example
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
57
Example
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
57
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
57
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
“test1”
s
57
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
“test1”
s
:Node2next
content
prev
57
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
“test1”
s
:Node2next
content
prev
57
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
“test1”
s
:Node2next
content
prev
58
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
“test1”
s
:Node2next
content
prev
58
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
“test1”
s
:Node2next
content
prev
“test2”
58
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
“test1”
s
:Node2next
content
prev
:Node2next
content
prev
“test2”
58
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
“test1”
s
:Node2next
content
prev
:Node2next
content
prev
“test2”
58
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
“test1”
s
:Node2next
content
prev
:Node2next
content
prev
“test2”
59
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
“test1”
:Node2next
content
prev
“test2”
:Node2next
content
prev
59
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
“test1”
:Node2next
content
prev
“test2”
:Node2next
content
prev
59
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
“test1”
:Node2next
content
prev
“test2”
:Node2next
content
prev
59
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
:Node2next
content
prev
“test2”
60
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
“test2”
:Node2next
content
prev
60
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
“test2”
:Node2next
content
prev
60
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
“test2”
:Node2next
content
prev
60
Example
:FifoQtail
head
FifoQ q;q = new FifoQ();String s;s = “test1”;q.addToQ(s);s = “test2”;q.addToQ(s);while(!q.isEmpty()) q.deleteFromQ();
q
61
Problem Statement
Write an application that reads in a text file organized in the manner shown below and displays the final course grades.The course grades are computed differently for the undergraduate and graduate students based on the formulas listed on page 710. The input text file format is as follows:
• A single line is used for information on one student. • Each line uses the format <Type> <Name> <Test 1> <Test 2> <Test 3> where <Type> designates either a graduate or an
undergraduate student,<Name> designates the student’s first and last
name, and <Test i> designates the ith test score. • End of input is designated by the word END. The case
of the letters is insignificant.
Overall Plan
Tasks Read an input file Compute the course grades Print out the result
Input file format:
62
<Type> <Name> <Test 1> <Test 2> <Test 3>U John Doe 87 78 90G Jill Jones 90 95 87G Jack Smith 67 77 68U Mary Hines 80 85 80U Mick Taylor 76 69 79END
63
Development Steps
We will develop this program in five steps:1. Start with the program skeleton.Define the
skeleton ComputeGrades classes.2. Implement the printResult method.Define any
other methods necessary to implement printResult.
3. Implement the computeGrade method.Define any other methods necessary to implement computeGrade.
4. Implement the readData method.Define any other methods necessary to implement readData.
5. Finalize and look for improvements.
64
Step 1 Design
We start with a program skeleton. We will define two constructors so the
programmer can create a roster of default size or the size of her choice.
65
Step 1 Code
Directory: Chapter13/Step1
Source Files: ComputeGrades.java
Program source file is too big to list here. From now on, we askyou to view the source files using your Java IDE.
66
Step 1 Test
We include a temporary output statement inside the (currently stub) method we define.
We run the test main class and verify that the methods are called correctly.
67
Step 2 Design We design and implement the printResult
method We use the helper class OutputBox for
displaying the result.
for each element i in the roster array {
output the name of roster[i];
output the test scores of roster[i];
output the course grade of roster[i];
skip to the next line;
}
68
Step 2 Code
Directory: Chapter13/Step2
Source Files: ComputeGrades.java
69
Step 2 Test
We verify the temporary readData method is working correctly. This confirms that we are using the correct student classes and using their methods correctly.
We verify the printResult method does indeed display the data in our desired format.
70
Step 3 Design
70
Step 3 Design
We design and implement the computeGrade method.
70
Step 3 Design
We design and implement the computeGrade method.
The code for actually determining the course grade is embedded in individual student classes
70
Step 3 Design
We design and implement the computeGrade method.
The code for actually determining the course grade is embedded in individual student classes So the code to add to the ComputeGrades class is
very simplistic.
70
Step 3 Design
We design and implement the computeGrade method.
The code for actually determining the course grade is embedded in individual student classes So the code to add to the ComputeGrades class is
very simplistic. This is a direct benefit of using polymorphism
effectively.
71
Step 3 Code
Directory: Chapter13/Step3
Source Files: ComputeGrades.java
72
Step 3 Test
We will repeat the same test routines from Step 2. Instead of seeing four asterisks, we should be
seeing the correct grades. We test both the passing and not passing test
scores.
73
Step 4 Design We design and implement the core
functionality of the program—the readData method
We can express its logic as
get the filename from the user;
if (the filename is provided) read in data and build the roster array;
else output an error message;
74
The buildRoster Method
set bufReader for input;
while ( !done ) {
line = get next line;
if (line is END) {
done = true;
} else {
student = createStudent( line );
if (student != null) {
roster[studentCount] = student; //add to roster
studentCount++; } } }
74
The buildRoster Method
The logic of the workhorse private method buildRoster is as follows:
set bufReader for input;
while ( !done ) {
line = get next line;
if (line is END) {
done = true;
} else {
student = createStudent( line );
if (student != null) {
roster[studentCount] = student; //add to roster
studentCount++; } } }
75
The createStudent Method
StringTokenizer parser = new StringTokenizer( line );
String type;
try {
type = parser.nextToken();
if (type.equals(UNDER_GRAD) || type.equals(GRAD)) {
student = newStudentWithData(type, parser);
} else { //invalid type is encountered
student = null;
}
} catch (NoSuchElementException e) { //no token
student = null;
}
return student;
75
The createStudent Method We use the StringTokenizer class to break
down items in a single line of input
StringTokenizer parser = new StringTokenizer( line );
String type;
try {
type = parser.nextToken();
if (type.equals(UNDER_GRAD) || type.equals(GRAD)) {
student = newStudentWithData(type, parser);
} else { //invalid type is encountered
student = null;
}
} catch (NoSuchElementException e) { //no token
student = null;
}
return student;
76
Step 4 Code
Directory: Chapter13/Step4
Source Files: ComputeGrades.java
77
Step 4 Test
77
Step 4 Test We run through a more complete testing routine in this
step.We need to run the program for various types of input files. Some of the possible file contents are as follows:
78
Step 5: Finalize and Improve
78
Step 5: Finalize and Improve
We finalize the program by correcting any remaining errors, inconsistency, or unfinished methods.
78
Step 5: Finalize and Improve
We finalize the program by correcting any remaining errors, inconsistency, or unfinished methods.
We want to review the methods and improve them as necessarily.
78
Step 5: Finalize and Improve
We finalize the program by correcting any remaining errors, inconsistency, or unfinished methods.
We want to review the methods and improve them as necessarily.
One problem (which would have been identified in step 4 testing) we need to correct is the missing method for expanding the roster array when the input file includes more student entries than the set default size of 25. We leave this method as Exercise 3. We also leave some of the possible improvements as exercises.
Recommended