Top Banner
Java I--Copyright © 2000-2002 Tom Hunter
118
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Page 2: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Chapter 9

Object-Oriented Programming: Part II

Page 3: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Implicit Subclass-object

toSuperclass-object

Conversion

Page 4: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

• Joe was feeling entrepreneurial, and so he decided to buy a piece of land in Arkansas. • Joe paid $50 for what the deed described as a wooden shack in the swamp.

• But, to his great surprise, when he got there, Joe discovered he hadn’t bought a shack in a swamp, but rather, the Taj Mahal on a beautiful lake. Joe was ecstatic.

• Joe got more than he was promised.

Page 5: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

• Mary was feeling entrepreneurial, and so she decided to buy a huge Mansion on an estate in Arkansas. • Mary paid $5 Million for what the deed described as a palatial estate on 40 acres.

• But, to her great surprise, found she hadn’t bought a magnificent Mansion and estate, but rather, a Doublewide trailer next to a dump. Mary was horrified.

• Mary got less than was promised.

Page 6: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

• Joe’s situation is akin to Referring to a Subclass object with a Superclass reference.

You get more than you expected. It’s a pleasant surprise.

SuperclassRef = new SubclassObject

Page 7: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

• Mary’s situation is akin to Referring to a Superclass object with a Subclass reference .

You get less than you expected. It’s a tragic mistake.

SubclassRef = new SuperclassObject

Page 8: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Implicit Subclass-object to Superclass-object Conversion

• There are four possible conversions that can occur:

1.) Refer to a Superclass object with a Superclass reference.

This is routine

Page 9: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Implicit Subclass-object to Superclass-object Conversion

2.) Refer to a Subclass object with a Subclass reference.

This is also routine

Page 10: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Implicit Subclass-object to Superclass-object Conversion

3.) Refer to a Subclass object with a Superclass reference

This is safesafe because the Subclass object isis an object of its Superclass.

Such code can only refer to Superclass methods.

Page 11: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Why might want to do that?

Suppose many classes inherit from one Superclass. • You can make an array of Superclass

references. • Then, you can treat them all the same,

as if they really were all Superclassobjects.

• As long as you call methods that exist inthe Superclass (but were overriddenby each of the various Subclasses), then the runtime system calls the correct overridden method for each one!

Page 12: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

This process is known as...

Page 13: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Implicit Subclass-object to Superclass-object Conversion

4.) Refer to a Superclass object with aSubclass reference .

This is a syntax error! It doesn’t make sense. It is only remotely possible ifif the Subclass is explicitly cast into a Superclass reference, which is a way of telling the compiler you are doing this damn-fool thing with your eyes open.

Page 14: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Implicit Subclass-object to Superclass-object Conversion

So, why is that a problem?

Here’s the problem:A Subclass contains more and does more than its

Superclass parent.

If you use a Subclass reference to point to a Superclass object, you are implying that the object has more data variables available than it really does—and if someone made that assumption—they would be sorely mistaken.

Page 15: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

The Right Way to Use

Polymorphism

Page 16: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

class Employee{

private String ssn;

public Employee(){

ssn = "";}

public Employee( String soc_num ){

ssn = soc_num;}

public String getSSN(){

return ssn;}

public double calcPay(){

return 0;}

}

Employee is our Superclass. As we see, it contains the instance

variable String ssn, a Constructor, the Accessor method getSSN() and the

emptyempty method calcPay(), which we will need to override in

all the Subclasses because they will all need to calculate pay

differently.

Page 17: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

class HourlyEmployee extends Employee{

double hourlyRate;int hoursWorked;

public HourlyEmployee(){

hourlyRate = 0.0;hoursWorked = 0;

}

public void setHourlyRate( double rate ){

hourlyRate = rate;}

public void setHoursWorked( int hours ){

hoursWorked = hours;}

public double calcPay(){

return hourlyRate * hoursWorked;}

}

Instance variables specific to the Subclass

Default Constructor

The overridden method inherited from the Superclass.

Page 18: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

public class DemoPolymorphism{

double pay = 0;public DemoPolymorphism(){

Employee supEmp = new HourlyEmployee();HourlyEmployee subHrEmp = new HourlyEmployee();

pay = supEmp.calcPay();System.out.println( "Superclass pay = " + pay );

subHrEmp.setHourlyRate( 5.65 );subHrEmp.setHoursWorked( 20 );pay = subHrEmp.calc_Pay();System.out.println( "Subclass pay = " + pay );

supEmp = subHrEmp;pay = supEmp.calcPay();System.out.println( "Superclass pay = " + pay );

}public static void main( String[] args ){

DemoPolymorphism demo = new DemoPolymorphism();System.exit( 0 );

}}

We declare a reference to an object of type Employee called supEmp. However, we instantiate an HourlyEmployee object and assign the reference to the Superclass Employee. This works because—after all—HourlyEmployee isis an Employee.

Page 19: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

public class DemoPolymorphism{

double pay = 0;public DemoPolymorphism(){

Employee supEmp = new HourlyEmployee();HourlyEmployee subHrEmp = new HourlyEmployee();

pay = supEmp.calcPay();System.out.println( "Superclass pay = " + pay );

subHrEmp.setHourlyRate( 5.65 );subHrEmp.setHoursWorked( 20 );pay = subHrEmp.calc_Pay();System.out.println( "Subclass pay = " + pay );

supEmp = subHrEmp;pay = supEmp.calcPay();System.out.println( "Superclass pay = " + pay );

}public static void main( String[] args ){

DemoPolymorphism demo = new DemoPolymorphism();System.exit( 0 );

}}

Page 20: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Superclass pay = 0.0Subclass pay = 113.0Superclass pay = 113.0Press any key to continue . . .

Page 21: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

The Wrong Way to Use Polymorphism—a Syntax

Error—(Without An Explicit Cast)

Page 22: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

public class CastSubTypeReftoSuperTypeObject{

double pay = 0;public CastSubTypeReftoSuperTypeObject(){ // Syntax Error ! ! ! HourlyEmployee subHrEmp = new Employee(); // Error!

// The error is not yet revealed. pay = subHrEmp.calcPay(); System.out.println( "Subclass pay = " + pay );

// Error because the object doesn’t have these // methods available.

subHrEmp.setHourlyRate( 5.67 ); subHrEmp.setHoursWorked( 20 ); pay = subHrEmp.calcPay(); System.out.println( "Subclass pay = " + pay );}public static void main( String[] args ){ CastSubTypeReftoSuperTypeObject demo; demo = new CastSubTypeReftoSuperTypeObject();

System.exit( 0 );}

}

In the program, we know that subHrEmp was declared as a type HourlyEmployee. But instead of getting a Mansion (HourlyEmployee), the reference was assigned to a Doublewide Trailer (Employee). The object doesn’t have these methods and these message calls won’t work!

Page 23: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

C:\CastSubTypeReftoSuperTypeObject.java:59: Incompatible type for declaration. Explicit cast needed to convert Employee to HourlyEmployee.

HourlyEmployee subHrEmp = new Employee(); // Error! ^

1 error

Tool completed with exit code 1

At this point, the compiler is extremely unhappy.So, let’s give it what it is specifically asking for—an explicit cast—and see what happens then.

Page 24: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

public class CastSubTypeReftoSuperTypeObject{

double pay = 0;public CastSubTypeReftoSuperTypeObject(){ // Now we’ve Band-Aided the Error with An

// Explicit cast HourlyEmployee subHrEmp; subHrEmp = (HourlyEmployee) new Employee();

// The error is not yet revealed. pay = subHrEmp.calcPay(); System.out.println( "Subclass pay = " + pay );

// Error because the object doesn’t have these // methods available.

subHrEmp.setHourlyRate( 5.67 ); subHrEmp.setHoursWorked( 20 ); pay = subHrEmp. calcPay(); System.out.println( "Subclass pay = " + pay );}public static void main( String[] args ){ CastSubTypeReftoSuperTypeObject demo; demo = new CastSubTypeReftoSuperTypeObject();

System.exit( 0 );}

}

Page 25: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Exception in thread "main" java.lang.ClassCastException: Employee at CastSubTypeReftoSuperTypeObject.<init>(CastSubTypeReftoSuperTypeObject.java:60) at CastSubTypeReftoSuperTypeObject.main(CastSubTypeReftoSuperTypeObject.java:75)

Press any key to continue . . .

At this stage, the compiler is incensed—it trusted us when we asked for that Explicit cast, and look what happened.

Page 26: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Polymorphism and

Dynamic Binding

Page 27: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Polymorphism and Dynamic Binding

Say that we have a bunch of objects that are all Shapes:

Circles,Squares,Triangles,Trapezoids, etc.

If we want to draw them all, we could use a large switch statement that asks if the object is a circle, do this. If a square, do this. If a triangle, do that...

Page 28: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Polymorphism and Dynamic Binding

The big switch could work okay, but if we decided to add a parallelogram to our shapes, then we would have to remember to add another branch to our switch statement.

Every place we wanted to do some behavior based on the shape, we would have to change our logic.

What a pain!

Page 29: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Polymorphism and Dynamic Binding

Polymorphism can save us that trouble—and make programs that will work with Shapes that hadn’t even been thought of when the class was written.

With Polymorphism, the objects themselves know what kind of object they are, and they do the right behavior based on their internal awareness of their own type!

Page 30: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Polymorphism and Dynamic Binding

In our Shapes example, we could assume that each shape Subclass that inherits off of the master Superclass—Shape—would have a draw() method.

Page 31: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Polymorphism and Dynamic Binding

That draw() method would detail exactly how to generate the Square or the Circle or the Triangle.

Each shape subclass knows how to draw itself.

Certainly, we could go through the trouble of drawing each Shape one by one.

Page 32: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Polymorphism and Dynamic Binding

But… wouldn’t it be nice if we could just treat all those various Shape Subclasses as copies of the Superclass?

Then, we could create an array of Superclass references that actually are initialized with Subclass objects.

Page 33: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Polymorphism and Dynamic Binding

We could move through the array calling the draw() method of the Superclass for each element in the array.

The overridden draw() methods in each Subclass shape could take care of drawing the shape the right way.

Easy, right?

Page 34: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Polymorphism and Dynamic Binding

Therefore, to make this work, the only thing we have to remember is:

• Declare draw() in the Superclass.

• Then, override draw() in each of theSubclasses to draw the correct Shape.

Page 35: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Polymorphism and Dynamic Binding

• The Run-Time Type Identification systemwill choose the correct subclass’sdraw() method dynamically—i.e.,on-the-fly— at execution time.

• This is called dynamic method bindingdynamic method binding,and it makes Polymorphism work.

Polymorphism relies on Dynamic BindingDynamic Binding.

Page 36: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Polymorphism and Dynamic Binding

PolymorphismPolymorphism.

• Allows you to process Superclass objects in a Generic way.

• Only the parts of a program that needspecific knowledge of the new classmust be tailored specifically to thenew class.

Page 37: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

final Variables,final Methods

andfinal Classes

Page 38: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

final Variables, final Methods and final Classes

• final variables—means they can’t be changed after they are declared.

( These variables must be initializedwhen they are declared. )

Page 39: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

final Variables, final Methods and final Classes

• final methods—means they can’t be overridden in any subclass.

• This allows the compiler to “inline” the code, or remove the overhead of the method call.

Page 40: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

final Variables, final Methods and final Classes

• Declaring a methodstatic or private

automatically makes it final .

Page 41: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

final Variables, final Methods and final Classes

• final class. This means that nothing can ever inherit from this class.

• A final class can never be a Superclass, which is another way of saying it can never spawn any Subclasses.

Page 42: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

final Variables, final Methods and final Classes

• We also point out that all the methods in a final class might as well be final (they are) because they can never be overridden.

Therefore:“A class declared final cannot be

extended and every method is implicitly final.”

Page 43: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Opposite of final

class is anabstract Superclass

Page 44: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

abstract Superclass

• Whereas a final class CANNOT ever be a Superclass (meaning, no Subclass can ever inherit from it)

• An abstract Superclass MUST be Subclassed.

• I.e., an abstract Superclass can’t be instantiated.

Page 45: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

abstract Superclass

• The whole point of making an abstract Superclass is so it will be Subclassed.

What Do We Need abstract Superclasses?• An abstract Superclass defines a common interface for the many Subclasses.

• It forces the Subclasses to all be build in a similar way.

Page 46: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

abstract Superclass

• Although an abstract Superclass can have instance variables and Constructor methods, all of its other methods are declared as abstract .

Page 47: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

abstract class

vs.

concrete class

Page 48: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

• shape is a generic class. Since shape really can’t even draw itself, we would never want to instantiate a “shape ”.

• Instead, we would always choose to instantiate some other specific kind of shape—such as a Square, Circle or Rectangle—that couldcould draw itself.

abstract Superclass

Page 49: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

• shape is merely the template, and thus, it presents a good candidate for being an abstract class.

abstract Superclass

Page 50: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

• If a class has any method that is abstract, then the class MUST be abstract.

• Whenever you decide to Subclass a class from that abstract Superclass, then you MUST override any method that is defined as abstract.

abstract Superclass

Page 51: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

• If you don’t override that abstract method, then it is inherited in your subclass.

• It is inherited as an abstract method and, in turn, it contaminates your Subclass.

• It makes your class—by default—also an abstract class.

abstract Superclass

Page 52: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

public class MustBeAbstract{ public abstract void doSomething();}

This class contains a method that is abstract. Therefore, the method:

1) Cannot contain a “body” and,2) The entire class must be declared abstract.

Page 53: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

public abstract class MustBeAbstract{ public abstract void doSomething(); }

These three things must be in place to successfully make an abstract class.

Page 54: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

abstract class MustBeAbstract{ public abstract void doSomething();}

public class TestAbstract{

public static void main( String args[] ){ MustBeAbstract mba = new MustBeAbstract(); System.exit( 0 );}

}

• Here we are trying to instantiate this abstract class.• As we expected, the compiler complains loudly.

C:\TestAbstract.java:11: class MustBeAbstract is an abstract class. It can't be instantiatedIt can't be instantiated..

MustBeAbstract mba = new MustBeAbstract(); ^

1 error

Page 55: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

abstract class MustBeAbstract{ public abstract void doSomething();}class SubMustBe extends MustBeAbstract{

public void anotherThing(){}

}public class TestAbstract{

public static void main( String args[] ){ SubMustBe smb = new SubMustBe(); System.exit( 0 );}

} • So, we will create a subclass and see if that makes the compiler any happier.

Page 56: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

C:\TestAbstract.java:5: class SubMustBe must be declared abstract. It does not define void doSomething() from class MustBeAbstract.

class SubMustBe extends MustBeAbstract ^

C:\TestAbstract.java:15: class SubMustBe is an abstract class. It can't be instantiated.

SubMustBe smb = new SubMustBe(); ^

2 errors

What went wrong?Well, since we didn’t override the abstract method doSomething(), we inherited

the abstract method into our class SubMustBe. Since we had a method that

was abstract, the whole class had to be declared abstract.

Page 57: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

abstract class MustBeAbstract{ public abstract void doSomething();}class SubMustBe extends MustBeAbstract{

public void doSomething(){}

}public class TestAbstract{

public static void main( String args[] ){ SubMustBe smb = new SubMustBe(); System.exit( 0 );}

}• Now we have overridden the abstract method and the compiler is happy.

Page 58: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

One last issue remains:• We now know that we cannot instantiate

an abstract class.

• But… can we create a reference to an abstract class?

abstract Superclass

Absolutely!

Page 59: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Why might we want to create a reference to an abstract class?

abstract Superclass

To create an array and use Polymorphism!

Page 60: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

A Payroll System using

Polymorphism

Page 61: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

A Payroll System using Polymorphism

( Turn to page 414)

• The following example will show how one would design a Payroll system using an abstract class and abstract methods.

Page 62: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

// Abstract base class Employee [ page 414 ]public abstract class Employee{ private String firstName; private String lastName;

public Employee( String first, String last ) { firstName = first; lastName = last; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public String toString() { return firstName + ' ' + lastName; }

public abstract double earnings(); }

This class Employee is abstract because it

contains the abstract method earnings(), which therefore must be overridden in any class that expects to inherit

from Employee .We chose to make

earnings() abstract because we need to calculate earnings

differently depending on the kind of employee.

Page 63: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

public final class Boss extends Employee{ private double weeklySalary;

public Boss( String first, String last, double s) { super( first, last ); // call superclass constructor setWeeklySalary( s ); } public void setWeeklySalary( double s ) { weeklySalary = ( s > 0 ? s : 0 ); } public double earnings() { return weeklySalary; } public String toString() { return "Boss: " + super.toString(); }}

This method overrides the abstract method inherited from the Superclass.

Page 64: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

A Payroll System using Polymorphism

( Turn to page 418)

• The driver application Test.java shows Polymorphism in action.

• It shows how we use the Superclass reference.

• Although we’re doing the same thing as we process through the various employees, each one is calculating its own pay in a different way!

Page 65: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

public class Test{ public static void main( String args[] ) { Employee ref; // superclass reference String output = "";

Boss b = new Boss( "John", "Smith", 800.00 ); CommissionWorker c = new CommissionWorker( "Sue", "Jones", … 150); PieceWorker p = new PieceWorker( "Bob", "Lewis", 2.5, 200 ); HourlyWorker h = new HourlyWorker( "Karen", "Price", 13.75, 40 );

ref = b; // Employee reference to a Boss output += ref.toString() + " earned $" + ref.earnings(); ref = c; // Employee reference to a CommissionWorker output += ref.toString() + " earned $” + ref.earnings(); ref = p; // Employee reference to a PieceWorker output += ref.toString() + " earned $" + ref.earnings();

ref = h; // Employee reference to an HourlyWorker output += ref.toString() + " earned $" + ref.earnings();

System.out.println( “” + output ); System.exit( 0 ); }}

We start off making a reference to the abstract

Superclass Employee. Remember, although we can’t instantiate an abstract class, we sure can make a reference

to one.

Page 66: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

public class Test{ public static void main( String args[] ) { Employee ref; // superclass reference String output = "";

Boss b = new Boss( "John", "Smith", 800.00 ); CommissionWorker c = new CommissionWorker( "Sue", "Jones", … 150); PieceWorker p = new PieceWorker( "Bob", "Lewis", 2.5, 200 ); HourlyWorker h = new HourlyWorker( "Karen", "Price", 13.75, 40 );

ref = b; // Employee reference to a Boss output += ref.toString() + " earned $" + ref.earnings(); ref = c; // Employee reference to a CommissionWorker output += ref.toString() + " earned $” + ref.earnings(); ref = p; // Employee reference to a PieceWorker output += ref.toString() + " earned $" + ref.earnings();

ref = h; // Employee reference to an HourlyWorker output += ref.toString() + " earned $" + ref.earnings();

System.out.println( “” + output ); System.exit( 0 ); }}

Next, we go ahead and instantiate each of the

Subclasses and assign them to appropriate references for

the various types of Employee.

Page 67: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

public class Test{ public static void main( String args[] ) { Employee ref; // superclass reference String output = "";

Boss b = new Boss( "John", "Smith", 800.00 ); CommissionWorker c = new CommissionWorker( "Sue", "Jones", … 150); PieceWorker p = new PieceWorker( "Bob", "Lewis", 2.5, 200 ); HourlyWorker h = new HourlyWorker( "Karen", "Price", 13.75, 40 );

ref = b; // Employee reference to a Boss output += ref.toString() + " earned $" + ref.earnings(); ref = c; // Employee reference to a CommissionWorker output += ref.toString() + " earned $” + ref.earnings(); ref = p; // Employee reference to a PieceWorker output += ref.toString() + " earned $" + ref.earnings();

ref = h; // Employee reference to an HourlyWorker output += ref.toString() + " earned $" + ref.earnings();

System.out.println( “” + output ); System.exit( 0 ); }}

We reassign each of these Employee Subclasses to the Superclass. Using the Superclass reference ref, we call the methods toString() and earnings() that also exist in the Superclass. The Runtime identifies that—in fact—this ref reference is really pointing to a different kind of object. So the Runtime performs the correct overridden methods.

Page 68: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

public class Test{ public static void main( String args[] ) { Employee ref; // superclass reference String output = "";

Boss b = new Boss( "John", "Smith", 800.00 ); CommissionWorker c = new CommissionWorker( "Sue", "Jones", … 150); PieceWorker p = new PieceWorker( "Bob", "Lewis", 2.5, 200 ); HourlyWorker h = new HourlyWorker( "Karen", "Price", 13.75, 40 );

ref = b; // Employee reference to a Boss output += ref.toString() + " earned $" + ref.earnings(); ref = c; // Employee reference to a CommissionWorker output += ref.toString() + " earned $” + ref.earnings(); ref = p; // Employee reference to a PieceWorker output += ref.toString() + " earned $" + ref.earnings();

ref = h; // Employee reference to an HourlyWorker output += ref.toString() + " earned $" + ref.earnings();

System.out.println( “” + output ); System.exit( 0 ); }}

This is

DynamicMethodBinding

Page 69: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

A Payroll System using Polymorphism

• If we had made ref an array, then this could have been done even easier.

• As we have seen, this can save you a lot of work.

• You write one driver program and it performs correctly without you having to code anything.

• The objects—through their overridden methods—make sure the right behavior happens!

Page 70: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Inheriting Interface

and Implementation

Page 71: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Inheriting Interface and Implementation

( Turn to page 421)

• This example shows how the abstract Superclass Shape[ abstract because the method getName() is declared as abstract and thus so must be the class ]defines the interface of all the objects that are Subclassed from it it.

Page 72: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Inheriting Interface and Implementation

• Along with the abstract method getName() that of course must be overridden, Shape contains two other methods area() and volume().

• Neither area() nor volume()are declared abstract so they may—if desired—be inherited directly withoutwithout being overridden.

Page 73: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Inheriting Interface and Implementation

• We describe this situation as being the interface merely because Shape gets to set the pace for its Subclasses.

• For example, Point inherits from Shape .

• Point overrides the getName() method (as it must) but it can live with the area() and volume() methods in Shape .

• The generic implementations in Shape are correct for Point .

Page 74: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Inheriting Interface and Implementation

( Turn to page 424)

• In the driver program, lines 140, 143 & 146 we see how an array of type Shape has been declared, and each element in the array has been initialized to hold a different one of the Subclasses.

• This allows them all to be treated in a polymorphic way.

Page 75: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Creating an

Interface

Page 76: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Creating an Interface

• When we used Shape in the previous example, we employed Inheritance .

• There is an alternative to using Inheritance, and it is called using an Interface.

• You are already quite familiar with interfaces—you’ve used them to handle events.

Page 77: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

interface “A Java programming language keyword used to define a collection of method definitions and constant values. It can later be implemented by classes that define this interface with the "implements" keyword.”

Page 78: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Creating an Interface

• To use an Interface, you must do two things:

• Use the implements keyword

• Override every method the interface has.

• If the implementing class fails to override any one method, then that method is inherited and the implementing class becomes abstract.

Page 79: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Creating an Interface

• You might choose to use an Interface instead of an abstract class when there is no default implementation to inherit.

1—No instance variables to inherit.2—No default method implementations.

When points 1 and 2 are true, it means you would be better off creating an Interface rather than inheriting an abstract class.

Page 80: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

public interface Shape{

public abstract double area();public abstract double volume();public abstract getName();

}

Page 81: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

package java.awt.event;

/* ActionListener.java 1.6 */

import java.util.EventListener;

/** * The listener interface for receiving action events. * * @version 1.6 11/23/96 * @author Carl Quinn */

public interface ActionListener extends EventListener {

/** * Invoked when an action occurs. */public void actionPerformed(ActionEvent e);

}

This is the actual code from Sun Microsystems that creates the

ActionListener

Page 82: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

package java.util;

/* EventListener.java */

/* A tagging interface that all event * listener interfaces must extend */

public interface EventListener {}

Finally, this is the code that creates the EventListener. This organizes

everything that follows.

Page 83: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Creating an Interface

• You may not understand the reason to implement an interface, if it doesn’t contain any code.

• However the real reason we bother is because you can implement multiple interfaces in one class.

Page 84: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Creating an Interface: Putting It Together

MySuper ms = new MySub();

MyInterface mi = new MyImplMyInterface();

• If the reference type is an INTERFACE, the object it refers to MUST be an object from a class which implements the interface—either directly or through inheritance.

Page 85: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Inner Classes:

“Getting In Touch with Your Inner Class”

Page 86: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

“Getting in Touch with Your Inner Class”*

Being an object like me isn't as fun as you might think.

It gets lonely...

Out here... on the heap... alone.

* Adapted from http://www.javaranch.com/campfire/StoryInner.jsp

Page 87: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

“Getting in Touch with Your Inner Class”

Not to mention the horror—the emotional devastation—when you feel your last reference slip away and it hits you—you've just become food for the garbage collector

* Adapted from http://www.javaranch.com/campfire/StoryInner.jsp

Page 88: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

“Getting in Touch with Your Inner Class”

But you know what helps? Having an inner class. An inner class can ease the loneliness... as long as somebody makes an instance of that inner class. All I really want is someone to bond with.

* Adapted from http://www.javaranch.com/campfire/StoryInner.jsp

Page 89: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

“Getting in Touch with Your Inner Class”

* Adapted from http://www.javaranch.com/campfire/StoryInner.jsp

Page 90: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

“Getting in Touch with Your Inner Class”

Someone to share my most private thoughts (and variables and methods). Someone who knows EVERYTHING about me. An intimate relationship shared between two objects -- an outer and an inner.

* Adapted from http://www.javaranch.com/campfire/StoryInner.jsp

Page 91: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

“Getting in Touch with Your Inner Class”

I'm very protective of my inner class. If somebody wants to instantiate my inner class, they MUST go through me—an object of the outer class.

* Adapted from http://www.javaranch.com/campfire/StoryInner.jsp

Page 92: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

“Getting in Touch with Your Inner Class”

My inner class can't exist on its own. I, as an instance of the outer class, can live on my own (however unhappily). You don't have to make an instance of an inner class in order to have an instance of the outer class. But you can NEVER make an instance of my inner class without an outer object to "bind" it to.

* Adapted from http://www.javaranch.com/campfire/StoryInner.jsp

Page 93: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

“Getting in Touch with Your Inner Class” My inner class needs me.

We have that special bond.

It makes life on the garbage-collectible heap bearable.

* Adapted from http://www.javaranch.com/campfire/StoryInner.jsp

Page 94: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

class Outer{ private int size ; private String thoughts = "My outer thoughts";

class Inner { String innerThoughts = "My inner thoughts";

void doStuff() { // inner object has its own "this" System.out.println( innerThoughts );

// and it also has a kind of "outer this" // even for private data of outer class System.out.println(thoughts); } }}

OK, but nothing really happens until somebody makes an instance of BOTH classes...

Page 95: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

class TestMe{ public static void main( String args[] ) { // instantiate me, the outer object Outer o = new Outer();

}

}

Page 96: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

class TestMe{ public static void main( String args[] ) { // instantiate me, the outer object Outer o = new Outer();

// Inner i = new Inner(); // NO! Can't instantiate Inner by itself!

}

}

Page 97: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

class TestMe{ public static void main( String args[] ) { // instantiate me, the outer object Outer o = new Outer();

// Inner i = new Inner(); // NO! Can't instantiate Inner by itself!

Outer.Inner i = o.new Inner(); // now I have my special inner object i.doStuff(); // OK to call methods on inner object }

}

Page 98: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

“Getting in Touch with Your Inner Class”

* Adapted from http://www.javaranch.com/campfire/StoryInner.jsp

You can also instantiate both the outer class and inner class at the same time:

Inner i = new Outer().new Inner();

Page 99: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

That shows you need an outer object, so that you can ask it to make an inner object. In this example, you didn't even keep a reference to the outer object... only the inner object i.

The inner object i still knows its outer object... its "outer this".

By the way, there is no keyword "outer this” —that's just a concept for the way inner objects behave.

They behave as if the outer object's variables were their own.)

Page 100: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

I hate static!

You've probably heard about static inner classes. Well, they don't deserve to be called inner classes!

A static inner class (an inner class marked as static) looks like this:

class Outer{

static class Inner{}

}

“Getting in Touch with Your Inner Class”

* Adapted from http://www.javaranch.com/campfire/StoryInner.jsp

Page 101: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

I don't like them because they don't give me that special object-to-object bond.

In fact, static inner classes aren't even supposed to be called inner classes at all.

Technically, they are "top-level nested classes".

“Getting in Touch with Your Inner Class”

* Adapted from http://www.javaranch.com/campfire/StoryInner.jsp

Page 102: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

A static nested class can be instantiated, but the object created doesn't share any special relationship with an outer object.

The static nested class is tied only to the outer class, not an instance of the outer class.

Outer.Inner i = new Outer.Inner();

“Getting in Touch with Your Inner Class”

* Adapted from http://www.javaranch.com/campfire/StoryInner.jsp

Page 103: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Inner Classes

Page 104: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Inner Classes

• The ability to create Inner Classes was added to Java with version 1.1.

• They are useful because they let you create a class close to where they are needed and are being used—inside another class.

• You can define an inner class:—inside another class,—inside a method or even—as part of an expression.

• Still, they behave just like any other class.

Page 105: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Inner Classes

• Inner classes can…—extend other classes and—implement interfaces.

• They come in four types:1— Static Inner Classes ( nested classes)2—Member Inner Classes3—Local Inner Classes4—Anonymous Inner Classes

Page 106: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Inner Classes

• Until now, all classes have been defined at file scope, where they are the outermost layer.

• Using Inner Classes, it is possible to nest one class within another one.

• Inner classes have the following characteristics:—They can access all the instance variables of the

so-called Outer Class.—They do not need any special handles.

Page 107: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Inner Classes

• Inner classes can be either named or anonymous.—An anonymous inner class is frequently

designated as the object that will do the event handling for an object.

—Also, you can have a separate inner class for every object that needs events handled.

Page 108: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Inner Classes

• Whenever we used the event-handling model, we havebeen careful to stress what it takes to be an eventhandler.

—the class has to implement the correct interfaceof the Event Handler.

—In the case of the ActionListener interface,the “handler” class only had to overridethe method:

actionPerformed( ActionEvent e )—This was required because this method was

declared abstract.

Page 109: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Inner Classes

• Well, any class that meets those requirements can be an event handler.

• After you declare your inner class someplace in your outer public class, you need to instantiate the inner class.

• Usual place is in the main() method.

Page 110: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

• Usually, the Inner class object is not much more complicated that this. • Notice it is declared as private• However, this only declares this “named” Inner class.• Now we need to instantiate it.• This class implements an ActionListener, so it is an ActionListener.

private class ActionEventHandlerimplements ActionListener

{public void actionPerformed( ActionEvent e ){

// do something with ‘e’}

}

ActionEventHandler handler = new ActionEventHandler(); button.addActionListener( handler );

Page 111: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

• Usually, it is possible to skip the declaring of the name.

• You can create a so-called “anonymous” inner class by just declaring at the last second right in the place where you need it.

button.addActionListener( new ActionListener() { public void actionPerformed(Action {

// do something with ‘e’ } }

Page 112: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

• The entire object is there, it just is doing what we need it without any extra work.

• Since the previous class merely implemented the ActionListener, then that class is anis an ActionListener.

• So, as long as our Inner Class also is anis an ActionListener, we are still okay.

button.addActionListener( new ActionListener() { public void actionPerformed(Action {

// do something with ‘e’ } }

Page 113: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Inner Classes

• Named inner classes can be public, protected, private or have package access.

• Every class—even an Inner Class—must have its own file that ends in .class.

• When you compile a class that contains an Inner Class, it makes a separate file.

Page 114: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

Inner Classes • Every class—even an Inner Class—must have its own file that ends in .class.

• When you compile a class that contains an Inner Class, it makes a separate file.

public class MyClass{

private class MyInner{}

}

• If this class is saved in a file called MyClass.java,it creates two class files.

MyClass.class

MyClass$MyInner.class

Page 115: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

import javax.swing.*;import java.awt.*;import java.awt.event.*;public class MyClass extends JApplet{

Container c;JButton but;public void init(){

c = getContentPane();but = new JButton( "Handle" );MyAction act = new MyAction();but.addActionListener( act );c.add( but );

}}class MyAction implements ActionListener{

public void actionPerformed( ActionEvent e ) { System.out.println( "Out" ); }

}

This is the setup we’re more used to. One public class MyClass with another class in the same file, MyAction. This results in:MyClass.class andMyAction.class.Notice, the closing brackets of each are outside of each other.

Page 116: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

import javax.swing.*;import java.awt.*;import java.awt.event.*;public class MyClass extends JApplet{

Container c;JButton but;public void init(){

c = getContentPane();but = new JButton( "Handle" );MyAction act = new MyAction();but.addActionListener( act );c.add( but );

}class MyAction implements ActionListener{ public void actionPerformed( ActionEvent e ) { System.out.println( "Out" ); }}

}

Now, we have the setup that produces the most basic “named” Inner class. Just by moving the closing curly bracket so as to enclose MyAction inside of MyClass, we have created two classes—one inner and the other the typical animal. This results in:MyClass.class andMyClass$MyAction.class

Page 117: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter

import javax.swing.*;import java.awt.*;import java.awt.event.*;public class MyClass extends JApplet{

Container c;JButton but;public void init(){

c = getContentPane();but = new JButton( "Handle" );

//MyAction act = new MyAction(); // not neededbut.addActionListener(

new ActionListener() {

public void actionPerformed( ActionEvent e) { System.out.println( "Out" ); }

} );

c.add( but );}

}

Finally, if we just transfer the entire MyAction structure to the inside of the: but.addActionListener() structure, we have our anonymous inner class:MyClass.class and MyClass$1.class

Also, now ActionListener is a

Constructor, so we need to add these parentheses

Page 118: Oop ii

Java I--Copyright © 2000-2002 Tom Hunter