Chapter 13 · 2 Introduction Inheritance and polymorphism are key concepts of Object Oriented...

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