68
Debugging, Interfaces, Debugging, Interfaces, Polymorphism Polymorphism

Debugging, Interfaces, Polymorphism. Debugging Debugging is –75% Psychological –20% Logic –5% Caffeine Java is not broken Our code is not broken Your

Embed Size (px)

Citation preview

Debugging, Interfaces, PolymorphismDebugging, Interfaces, Polymorphism

DebuggingDebugging

• Debugging is– 75% Psychological– 20% Logic– 5% Caffeine

• Java is not broken

• Our code is not broken

• Your code is broken!

• This is where test mains payoff!

• Work backwards...liberal application of "System.out.printf"

Mini-reviewMini-review• References: Pointers to objects. Include many of the classic confusing

things about pointers!

• Inheritence: defined with keyword "extends".

– Subclasses inherit all of the fields and methods of the parent class

– Define subclasses in their own file

• Arrays are objects which require a reference

Watch[] watchArray = new Watch[];

• For the most part avoid static

• Creating a (reference variable vs creating an instance)

TetrisBlock tb;

tb = new TetrisBlock();

Questions?Questions?

Multiple InheritanceMultiple Inheritance

Some languages allow multiple inheritance:

• Multiple inheritance leads to many potentially confusing naming problems (e.g. Pet.doYourThing() vs. Animal.doYourThing())

• Growing consensus: the benefits of multiple inheritance aren’t worth the problems.

• Java has single inheritance onlyonly.• Java doesn’t allow multiple inheritance• Well, there is a restricted kind that avoids most of the problems.

It involves using interfaces.

Animal

Dog

Pet

We’ve already seen one use of We’ve already seen one use of interfacesinterfaces

public class P1Constants{

public static final int FEETPERMILE = 5280;}

public class SomeOtherClass{

...public int convertFeet2Miles(int feet){

return feet * P1Constants.FEETPERMILE;}...

}

We’ve already seen one use of We’ve already seen one use of interfacesinterfaces

public interface P1Constants{

final int FEETPERMILE = 5280;}

public class SomeOtherClass implements P1Constants{

...public int convertFeet2Miles(int feet){

return feet * FEETPERMILE;}...

}

But the key feature...But the key feature...

Animal

Aquatic LandBased

Goldfish Shark Dog Cat Giraffe

I have this structure

But I want some of the animals to be Pets?

Pets will have names!Pets will have names!

public interface Pet

{

public String getName();

public void setName(String name);

}

Note: We don't define the variable name

So now if I want a dog to be a pet:So now if I want a dog to be a pet:

class Dog implements Pet {private String name;/* Plus other fields */

public String getName() {return name;

}

public void setName(String name) {this.name = name;

}/* Plus other methods */

}

Questions? Questions?

Questions?Questions?

Visibility and AccessVisibility and Access

Visibility Modifier:

Access by: public protected private

Every class Yes No* No

A subclass Yes Yes No

An instance of the class Yes Yes Yes

Always specify a visibility modifier.Guidelines:Only make public methods that are in the class’s “contract”Make all fields privateMake all other “private” methods protectedDon’t leave off the modifier unless you know about packages

Can an object use a field or call a method?

More PolymorphismMore Polymorphism

In Our Last Episode...In Our Last Episode...

Recall last lecture’s discussion of polymorphism.

PolymorphismPolymorphismclass Driver { public static void main (String[ ] argv) { Animal[ ] animalArray = new Animal[3]; int iIndex; animalArray[0] = new Bird( ); animalArray[1] = new Dog( ); animalArray[2] = new Fish( ); for (iIndex=0; iIndex < animalArray.length; iIndex++) { animalArray[iIndex].move( ); } // of for

} // of main} // of Driver

Output: Flap, flap, flap again Run, scratch, walk, run Swim, swim, swim, swim!

All animals can move,so any member of thearray can move

PolymorphismPolymorphismclass Driver { public static void main (String[ ] argv) { Animal[ ] animalArray = new Animal[3]; int iIndex; animalArray[0] = new Bird( ); animalArray[1] = new Dog( ); animalArray[2] = new Fish( ); for (iIndex=0; iIndex < animalArray.length; iIndex++) { animalArray[iIndex].move( ); } // of for

} // of main} // of Driver

Output: Flap, flap, flap again Run, scratch, walk, run Swim, swim, swim, swim!

All animals can move,so any member of thearray can move

This concept is a KEYfeature of any objectoriented language, notjust Java.

It is imperativeimperative that youunderstand how it works.

Let us review

RecallRecallclass Animal { public void move ( ) { System.out.println (“I am an animal and am moving.”); }} // of Animal

class Fish extends Animal { public void move( ) { System.out.println (“Swim, swim, swim, swim!”); }} // of Fish

class Bird extends Animal { public void move( ) { System.out.println (“Flap, flap, flap again”); }} // of Bird

class Dog extends Animal { public void move ( ) { System.out.println (“Run, scratch, walk, run”); }

public void bark ( ){ System.out.println (“Arf Arf”); }

} // of Dog

On the 7th Lecture, we createdOn the 7th Lecture, we createdmany animals . . . many animals . . .

... and it was good.... and it was good.

RecallRecallclass Driver { public static void main (String[ ] argv) { Animal[ ] animalArray = new Animal[3]; int iIndex; animalArray[0] = new Bird( ); animalArray[1] = new Dog( ); animalArray[2] = new Fish( ); for (iIndex=0; iIndex < animalArray.length; iIndex++) { animalArray[iIndex].move( ); } // of for

} // of main} // of Driver

Output: Flap, flap, flap again Run, scratch, walk, run Swim, swim, swim, swim!

We also noted that we could use polymorphism to hold an array of animals, and employ dynamic binding to invoke specific behaviors.

And so...And so...Let’s review the creation of an object, using a slightly more complex class example

class Animal { public int numLegs; public static int total = 0; public String strType;

public Animal (int numLegs){ this.numLegs = numLegs; strType = “Animal”; total++; } public void move ( ) { System.out.println (“I am an animal and am moving.”); } public String toString(){ return strType + “ with “ + numLegs + “ legs.”; }} // of Animal

This time, we have instance and class variables. The int total is a population counter. The int numLegs records the number of legs for the animal. The String strType describes the animal.

This may not be the best design. Don’t forget

this is an academicexercise. We’re doing

this for a reason.

And so...And so...Let’s review the creation of an object, using a slightly more complex class example

class Animal { public int numLegs; public static int total = 0; private String strType;

public Animal (int numLegs){ this.numLegs = numLegs; strType = “Animal”; total++; } public void move ( ) { System.out.println (“I am an animal and am moving.”); } public String toString(){ return strType + “ with “ + numLegs + “legs.”; }} // of Animal

The move() method is the same as before.We’ve added a constructor anda simple toString().

In a perfect world, we’d have room on the slides for theaccessors and modifiers.

And also...And also...

class Fish extends Animal { public Fish(int numLegs){ super(numLegs); strType = “Fish”; } public void move( ) { System.out.println (“Swim, swim, swim, swim!”); }} // of Fish

The Fish class is very muchthe same. We just add a newconstructor, which invokesthe parent constructor, andthen corrects the strTypeassignment.

And also...And also...class Bird extends Animal { public Bird(int numLegs){ super (numLegs); strType = “Bird”; } public void move( ) { System.out.println (“Flap, flap, flap again”); }} // of Bird

Same story with theBird class. We addeda new constructor, and

set the type appropriately.

And also...And also...class Dog extends Animal { public Dog(int numLegs){ super (numLegs); strType = “Dog”; } public void move ( ) { System.out.println (“Run, scratch, walk, run”); }

public void bark ( ){ System.out.println (“Arf Arf”); }

} // of DogSame story with theDog class. We added

a new constructor, andset the type appropriately.

And Finally...And Finally...

class Driver { public static void main (String[ ] argv) { Animal[ ] animalArray = new Animal[3]; int iIndex; animalArray[0] = new Bird(2); animalArray[1] = new Dog(3); animalArray[2] = new Fish(0); for (i=0; i < animalArray.length; i++) { System.out.println (animalArray[i].toString()); animalArray[i].move( ); } // of for System.out.println (“Total Count: “ + Animal.total);

} // of main} // of Driver

We also revise ourDriver class, passing inappropriate values to the

constructors. (We happen tohave a three-legged dog.)

What Happens?What Happens?class Animal { public int numLegs; public static int total = 0; private String strType;

public Animal (int numLegs){ this.numLegs = numLegs; strType = “Animal”; total++; } public void move ( ) { System.out.println (“I am an animal and am moving.”); } public String toString(){ return strType + “ with “ + numLegs + “ legs.”; }} // of Animal

class Fish extends Animal { public Fish(int numLegs){ super(numLegs); strType = “Fish”; } public void move( ) { System.out.println (“Swim, swim, swim, swim!”); }} // of Fish

class Bird extends Animal { public Bird(int numLegs){ super (numLegs); strType = “Bird”; } public void move( ) { System.out.println (“Flap, flap, flap again”); }} // of Bird

class Dog extends Animal { public Dog(int numLegs){ super (numLegs); strType = “Dog”; } public void move ( ) { System.out.println (“Run, scratch, walk, run”); }

public void bark ( ){ System.out.println (“Arf Arf”); }

} // of Dog

class Driver { public static void main (String[ ] argv) { Animal[ ] animalArray = new Animal[3]; int iIndex; animalArray[0] = new Bird(2); animalArray[1] = new Dog(3); animalArray[2] = new Fish(0); for (i=0; i < animalArray.length; i++) { System.out.println (animalArray[i].toString()); animalArray[i].move( ); } // of for

} // of main} // of Driver

If we run the Driver, what happens? Moreover, WHYWHY does it happen?

A Look At MemoryA Look At Memory

class Animal { public int numLegs; public static int total; private String strType;

public Animal (int numLegs){ this.numLegs = numLegs; strType = “Animal”; } public void move ( ) { System.out.println (“I am an animal and am moving.”); } public String toString(){ return strType + “ with “ + numLegs + “ legs.”; }} // of Animal

We intend to take a close look at these objects in memory. But before we do that, we have to condense what we’ve written.

We’ll need to agree on some symbols and a notation system.

AnimalAnimalint numLegsString strTypetoString();move();

We’ll represent Animal instances in memory as a box. We’llhave a little room for the variables, and a few key methods.

A Look At MemoryA Look At Memory

class Animal { public int numLegs; public static int total; private String strType;

public Animal (int numLegs){ this.numLegs = numLegs; strType = “Animal”; } public void move ( ) { System.out.println (“I am an animal and am moving.”); } public String toString(){ return strType + “ with “ + numLegs + “ legs.”; }} // of Animal

We intend to take a close look at these objects in memory. But before we do that, we have to condense what we’ve written.

We’ll need to agree on some symbols and a notation system.

AnimalAnimalint numLegsString strTypetoString();move();

Since an Animal inherits from Object (remember IS-A relationshipsare specified by inheritance), we also draw an Object box.

ObjectObjecttoString()

In future classes,you’ll learn aboutUML diagrams.But for now, it’s

all boxes and arrows.

A Look At MemoryA Look At Memory

class Animal { public int numLegs; public static int total; private String strType;

public Animal (int numLegs){ this.numLegs = numLegs; strType = “Animal”; } public void move ( ) { System.out.println (“I am an animal and am moving.”); } public String toString(){ return strType + “ with “ + numLegs + “ legs.”; }} // of Animal

Now, a Fish is more complex. It inherits from Animal which extends Object.

AnimalAnimalint numLegsString strTypetoString();move();

ObjectObjecttoString()

class Fish extends Animal { public Fish(int numLegs){ super(numLegs); strType = “Fish”; } public void move( ) { System.out.println (“Swim, swim, swim, swim!”); }} // of Fish

FishFishmove();

This wholearea is a Fishobject in memory.Since a Fish IS-AAnimal, and an Animal IS-A Object, we draw all three boxes to express one object

A Look At MemoryA Look At Memory

Thus, if we make a Fish instance, wehave a reference pointing to this block of memory that we’ve drawn.

AnimalAnimalint numLegs = 0String strTypetoString();move();

ObjectObjecttoString()

FishFishmove();

Fish fTemp;fTemp = new Fish(0);

fTemp

By convention, we will have the reference point to a particularportion of the block of memory, even though the entire block isone object. Since our reference is a Fish type, our arrow enters atthe Fish portion of the object in memory.

Recall Our Object Creation TimelineRecall Our Object Creation TimelineRemember that a call to the Fish(int) constructor involves an explicit Animal(int) constructor call. Even if we did not have this explicit call, Java would implicitly call the parent class constructor, just as it implicitly makes an Object when the Animal(int) constructor is invoked from the Fish(int) constructor.

AnimalAnimalint numLegs = 0String strTypetoString();move();

ObjectObjecttoString()

FishFishmove();

Fish fTemp = new Fish(0);

fTemp

AnimalAnimalint numLegs = 0String strTypetoString();move();

ObjectObjecttoString()

FishFishmove();

AnimalAnimalint numLegs = 0String strTypetoString();move();

ObjectObjecttoString()

FishFishmove();

To make a Fish, Java must first make an Animal.To make an Animal, Java must first make an Object.

11 22 33

Wow.Wow.

AnimalAnimalint numLegs = 0String strTypetoString();move();

ObjectObjecttoString()

FishFishmove();

Object oTemp;oTemp = new Fish(0);

oTemp

Notice something else. Since all Fish are Object types, we can have an Object reference pointing to this block of memory.

We adjust where the reference entersthe block of memory, that that it reflectsthe reference type.

A single Fish instance

Ahh. Ahh.

AnimalAnimalint numLegs = 0String strTypetoString();move();

ObjectObjecttoString()

FishFishmove();

Animal aTemp;aTemp = new Fish(0);

aTemp

So we can just make new reference types and have them point into our block at a different locations. By ‘twiddling’ the reference into our block of memory, we can polymorphpolymorph the object.

We adjust where reference points, sothat it reflects its type.

Hey, CoolHey, Cool

AnimalAnimalint numLegs = 3String strTypetoString();move();

ObjectObjecttoString()

FishFishmove();

ref

That’s a simple example of polymorphism.That’s a simple example of polymorphism.

FishFish

Hey, CoolHey, Cool

AnimalAnimalint numLegs = 3String strTypetoString();move();

ObjectObjecttoString()

FishFishmove();

ref

That’s a simple example of polymorphism.That’s a simple example of polymorphism.

AnimalAnimal

Hey, CoolHey, Cool

AnimalAnimalint numLegs = 3String strTypetoString();move();

ObjectObjecttoString()

FishFishmove();

ref

That’s a simple example of polymorphism.That’s a simple example of polymorphism.

It’s the same object inIt’s the same object inmemory. We just memory. We just

change the change the referencereference type pointing to it.type pointing to it.

ObjectObject

PolymorphismPolymorphism

AnimalAnimalint numLegs = 3String strTypetoString();move();

ObjectObjecttoString()

FishFishmove();

ref

Literally, polymorphism means “Many forms” So forLiterally, polymorphism means “Many forms” So forus we take it to imply, "One object; many forms”us we take it to imply, "One object; many forms”

<type><type>

One object

Many forms

ThusThus

AnimalAnimalint numLegs = 0String strTypetoString();move();

ObjectObjecttoString()

FishFishmove();

AnimalAnimalint numLegs = 3String strTypetoString();move();

ObjectObjecttoString()

DogDogmove();bark();

AnimalAnimalint numLegs = 2String strTypetoString();move();

ObjectObjecttoString()

BirdBirdmove();

So we have three box groupings that represent arbitrary instances of Fish, Dog and Bird, pointed to by any appropriate reference type.

Fish fTemp = new Fish(0);Dog dTemp = new Dog(3);Bird bTemp = new Bird(2);

fTemp dTemp bTemp

RecallRecallclass Animal { public int numLegs; public static int total = 0; private String strType;

public Animal (int numLegs){ this.numLegs = numLegs; strType = “Animal”; total++; } public void move ( ) { System.out.println (“I am an animal and am moving.”); } public String toString(){ return strType + “ with “ + numLegs + “ legs.”; }} // of Animal

class Fish extends Animal { public Fish(int numLegs){ super(numLegs); strType = “Fish”; } public void move( ) { System.out.println (“Swim, swim, swim, swim!”); }} // of Fish

class Bird extends Animal { public Bird(int numLegs){ super (numLegs); strType = “Bird”; } public void move( ) { System.out.println (“Flap, flap, flap again”); }} // of Bird

class Dog extends Animal { public Dog(int numLegs){ super (numLegs); strType = “Dog”; } public void move ( ) { System.out.println (“Run, scratch, walk, run”); }

public void bark ( ){ System.out.println (“Arf Arf”); }

} // of Dog

So we figured out how to represent inheritance in memory. Now recall that we also had our classes point to a String literal describing the type.

A String literal is, well, literallya String. It’ssomethingin quotes inyour sourcecode. Literallywhat’s there.

The Constant PoolThe Constant Pool

As it turns out, there’s an area of the Java Virtual Machine called the Constant PoolConstant Pool.. It’s a special area to hold declared constants (final variables), since they cannot be changed. As it turns out, this is where String literals are placed.

Animal aTemp;aTemp = new Bird(2);

aTemp

ObjectObjecttoString()

BirdBirdmove();

AnimalAnimalint numLegs = 2String strTypetoString();move();

Constant PoolConstant Pool

“Animal”“Fish”“Bird”“Dog”

ObjectObjecttoString()

BirdBirdmove();

AnimalAnimalint numLegs = 2String strTypetoString();move();

Constant PoolConstant Pool

“Animal”“Fish”“Bird”“Dog”

The Constant PoolThe Constant Pool

Since Strings are Objects, and are addressed through references, the strType variable in the Animal class points to one of these literals in the Constant Pool.

Animal aTemp;aTemp = new Bird(2);

aTemp

ObjectObjecttoString()

BirdBirdmove();

AnimalAnimalint numLegs = 2String strTypetoString();move();

Constant PoolConstant Pool

“Animal”“Fish”“Bird”“Dog”

The Constant PoolThe Constant Pool

Note that this is different for primitive instance variables. Primitives are not references. So we just write the value right next to the field

Animal aTemp;aTemp = new Bird(2);

aTemp

CONTRA

CONTRA

ObjectObjecttoString()

BirdBirdmove();

AnimalAnimalint numLegs = 2String strTypetoString();move();

In Fact...In Fact...

Constant PoolConstant Pool

In fact, the String strType also inherits from Object. So we could even draw the Constant Pool as a collection of objects with inheritance.

ObjectObjecttoString();

StringString“Animal”

ObjectObjecttoString();

StringString“Dog”

ObjectObjecttoString();

StringString“Fish”

ObjectObjecttoString();

StringString“Bird”

aTemp

Animal aTemp;aTemp = new Bird(2);

But this isgetting too

complicated.

What would Keanu Reeves say?What would Keanu Reeves say?

“Whoa.”

Constant PoolConstant Pool

“Animal”“Fish”“Bird”“Dog”

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

DogDogmove();bark();

So, we’ll abstract away mostof the details, and just notethat objects in Java are handled through references.

All of theobjects created byour Driver class have unique values (numLegs)and unique references.

Constant PoolConstant Pool

“Animal”“Fish”“Bird”“Dog”

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

Note also that if we assign theString strType to point to something else, it might not reference the Constant Pool.

Bird bTemp = new Bird(0);bTemp.setType (IOHelper.readLine());

ObjectObjecttoString()

StringString<whatever IOHelper returns>

Operations likenew String();substring();and IOHelper.readLine();cause the allocation of new String objects

What About Non-Instance Data?What About Non-Instance Data?

ObjectObjecttoString()

FishFishmove();

AnimalAnimalint numLegs = 3String strTypetoString();move();

ObjectObjecttoString()

DogDogmove();bark();

AnimalAnimalint numLegs = 0String strTypetoString();move();

The int numLegs was an instance variableinstance variable of the class Animal, and each instance had its own copy. But the variable int total--the population counter--was declared static. Thus, it was a classclass variablevariable. How can we account for this in our diagrams?

What About Non-Instance Data?What About Non-Instance Data?

It just so happens there is something called the Class Pool in Java, which holds information about each class used in your program. You can think of this as the “text” area where your code is kept. The other parts of memory are the “data” area where objects are kept. The Class Pool is like a country club. You have to have some class to be admitted.

class Animal { public int numLegs; public static int total = 0; private String strType;

public Animal (int numLegs){ this.numLegs = numLegs; strType = “Animal”; total++; } public void move ( ) { System.out.println (“I am an animal and am moving.”); } public String toString(){ return strType + “ with “ + numLegs + “ legs.”; }} // of Animal

Class PoolClass PoolObjectObject

toString()

FishFishmove();

AnimalAnimalint numLegs = 3String strTypetoString();move();

ObjectObjecttoString()

DogDogmove();bark();

AnimalAnimalint numLegs = 0String strTypetoString();move();

class Animal { public int numLegs; public static int total = 0; private String strType;

public Animal (int numLegs){ this.numLegs = numLegs; strType = “Animal”; total++; } public void move ( ) { System.out.println (“I am an animal and am moving.”); } public String toString(){ return strType + “ with “ + numLegs + “ legs.”; }} // of Animal

class Fish extends Animal { public Fish(int numLegs){ super(numLegs); strType = “Fish”; } public void move( ) { System.out.println (“Swim, swim, swim, swim!”); }} // of Fish

class Bird extends Animal { public Bird(int numLegs){ super (numLegs); strType = “Bird”; } public void move( ) { System.out.println (“Flap, flap, flap again”); }} // of Bird

class Dog extends Animal { public Dog(int numLegs){ super (numLegs); strType = “Dog”; } public void move ( ) { System.out.println (“Run, scratch, walk, run”); }

public void bark ( ){ System.out.println (“Arf Arf”); }

} // of Dog

class Driver { public static void main (String[ ] argv) { Animal[ ] animalArray = new Animal[3]; int iIndex; animalArray[0] = new Bird(2); animalArray[1] = new Dog(3); animalArray[2] = new Fish(0); for (i=0; i < animalArray.length; i++) { System.out.println (animalArray[i].toString()); animalArray[i].move( ); } // of for

} // of main} // of Driver

Class PoolClass PoolAs it turns out, the Class Pool is enormous (probably Olympic size). It holds not only your classes, but all the classes used by Java--String, Object, Integer, etc. Every class used to run your program gets loaded here.

Java uses the Class Pool to keep track of the working code and methods in each class.

Since static variables are “of the class” and not “of the instance”, they are kept as part of this storage device.

(In classAnimal)

static inttotal: 3

class Animal { public int numLegs; public static int total = 0; private String strType;

public Animal (int numLegs){ this.numLegs = numLegs; strType = “Animal”; total++; } public void move ( ) { System.out.println (“I am an animal and am moving.”); } public String toString(){ return strType + “ with “ + numLegs + “ legs.”; }} // of Animal

class Fish extends Animal { public Fish(int numLegs){ super(numLegs); strType = “Fish”; } public void move( ) { System.out.println (“Swim, swim, swim, swim!”); }} // of Fish

class Bird extends Animal { public Bird(int numLegs){ super (numLegs); strType = “Bird”; } public void move( ) { System.out.println (“Flap, flap, flap again”); }} // of Bird

class Dog extends Animal { public Dog(int numLegs){ super (numLegs); strType = “Dog”; } public void move ( ) { System.out.println (“Run, scratch, walk, run”); }

public void bark ( ){ System.out.println (“Arf Arf”); }

} // of Dog

class Driver { public static void main (String[ ] argv) { Animal[ ] animalArray = new Animal[3]; int iIndex; animalArray[0] = new Bird(2); animalArray[1] = new Dog(3); animalArray[2] = new Fish(0); for (i=0; i < animalArray.length; i++) { System.out.println (animalArray[i].toString()); animalArray[i].move( ); } // of for

} // of main} // of Driver

Class PoolClass Pool

(In classAnimal)

static inttotal: 3

That’s why we can use the class name to invoke class methods, or access class variables.

When we access instance variables, however, we must work through an instance of the class.

int x = Animal.total;

int leg = myDog.getLegCount();

(This assumes we havean accessor; there’s not enough room on these slides.)

Style Point:Style Point:

You can also access class members (static stuff) using instance references.

Integer iTemp = new Integer(3);

String strNumber = “42”;

int x = iTemp.parseInt(strNumber); // OK

int y = Integer.parseInt (strNumber); // better

There is, however, a conventionconvention, of using class names to accessclass methods/fields. Using an instance of the class also works;however, it gives the impression that it must be done through aninstance. So,

(1) Use what works. (2) But use what’s clear.

(Please take a moment to check that (Please take a moment to check that your socks were not knocked off your socks were not knocked off

during the previous slides...)during the previous slides...)

The organizing principle is the shared inherited relationship with Animal. Since Fish, Dog and Bird all extend from Animal, we can make an Animal array to hold different expressions of this class.

Back to PolymorphismBack to Polymorphism

So, we have these three blocks, representing objects in memory, each different, holding unique references and primitive values. How can these disparate objects be held in an array, which must be heterogeneous?

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

We could also have made an array of Object types. But we then will have problems invoking methods on members of this array, since Object lacks key methods--like move().

Back to PolymorphismBack to Polymorphism

So, we have these three blocks, representing objects in memory, each different, holding unique references and primitive values. How can these disparate objects be held in an array, which must be heterogeneous?

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

So we select Animal as our common type. It’s the most specific type, and yet is still held in common by all the members we plan to hold in the array.

Back to PolymorphismBack to Polymorphism

So, we have these three blocks, representing objects in memory, each different, holding unique references and primitive values. How can these disparate objects be held in an array, which must be heterogeneous?

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

Back to PolymorphismBack to Polymorphism

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

Recall that we can have many reference types pointing to the same Fish or Dog or Bird instance in memory. Thus, since arrays must be of a single type, we just polymorph any references we have into Animal references.

Bird bTemp = new Bird();Object oTemp = (Object) bTemp;Animal aTemp = (Animal) bTemp;

aTemp bTempoTemp

Here, the castingis not needed since we areupcastingupcasting.

It’s shown to be explicit.

Thus, when we have many objects in memory, we polymorph our references to the instances. This gives us an array of Animal types, even though each instance is a different subclass.

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

Animal [ ]Animal [ ]

final int length = 3

ObjectObject

toString();

Notice that the“int length”field of an array

is final. We can’tresize arrays;

we can only makenew larger

ones and copythe data over.

News Flash:Arrays are objectsas well, and extend

from Object.

[ 0 ] [ 1 ] [ 2 ]

Let’s invoke some methods on these objects.

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

Animal [ ]Animal [ ]

final int length = 3

ObjectObjecttoString();

Is our picture correct?

What if we executed this code:

Object oTemp;

oTemp = animalArray[1];

oTemp

No. The codeNo. The codeworks. But our drawing works. But our drawing is pointing to the wrongis pointing to the wrong

part of our objectpart of our object

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

Animal [ ]Animal [ ]

final int length = 3

ObjectObjecttoString();

Is our picture correct?

What if we executed this code:

Object oTemp;

oTemp = animalArray[1];

oTemp

Much better. ThisMuch better. Thisfussiness will payfussiness will pay

off shortly.off shortly.

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

Animal [ ]Animal [ ]

final int length = 3

ObjectObjecttoString();

Now, let’s add another line of code:

Object oTemp;

oTemp = animalArray[1];

oTemp.move();

oTemp

Does this work?

NO. The class Object

has no method called move()

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

Animal [ ]Animal [ ]

final int length = 3

ObjectObjecttoString();

The fix is in:

Object oTemp;oTemp = animalArray[1];Animal aTemp = (Animal) oTemp;

oTemp

aTemp

Note the explicitdown castingdown casting

was necessary.

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

Animal [ ]Animal [ ]

final int length = 3

ObjectObjecttoString();

The fix is in:

Object oTemp;oTemp = animalArray[1];Animal aTemp = (Animal) oTemp;aTemp.move();

oTemp

aTemp

Hmm... Let’s look atthis closely.

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

Animal [ ]Animal [ ]

final int length = 3

ObjectObjecttoString();

Object oTemp;oTemp = animalArray[1];Animal aTemp = (Animal) oTemp;aTemp.move();

oTemp

aTemp

ObjectObjecttoString()

FishFishmove();

AnimalAnimalint numLegs = 3String strTypetoString();move();

It looks like bothAnimal and Fishhave move() methods.

Which one gets called when the aTemp.move() line executes?

The reference typewe are using is an

Animal type. Would thatdetermine whether Animal

or Fish has their method called?

Dynamic BindingDynamic Binding

ObjectObjecttoString()

FishFishmove();

AnimalAnimalint numLegs = 3String strTypetoString();move();

Object oTemp;

oTemp = animalArray[1];

Animal aTemp = (Animal) oTemp;

aTemp.move();

aTemp

Here, the principle of dynamic bindingdynamic binding will ensure that at run time, the most specific behavior will be invoked. Here, the Fish move() method is more specific than its parent method. So, the Fish’s move() method gets called with the aTemp.move() line.

Understand this term. UnderstandUnderstand this term. Understandwhat is does. You WILL have many,what is does. You WILL have many,many, many, quiz and final exam many, many, quiz and final exam

question on this. It is a question on this. It is a CORECORE feature of any Object feature of any Object

Oriented language.Oriented language.

Sanity CheckSanity Check

ObjectObjecttoString()

FishFishmove();

AnimalAnimalint numLegs = 3String strTypetoString();move();

Object oTemp;

oTemp = animalArray[1];

Animal aTemp = (Animal) oTemp;

System.out.println (oTemp.toString());

oTemp

What about:

System.out.println ( ((Object)oTemp).toString() );

What Happens Here?

Does castingsomehowoverpowerdynamicbinding?

Sanity CheckSanity Check

ObjectObjecttoString()

FishFishmove();

AnimalAnimalint numLegs = 3String strTypetoString();move();

Object oTemp;

oTemp = animalArray[1];

Animal aTemp = (Animal) oTemp;

System.out.println (oTemp.toString());

oTemp

What about:

System.out.println ( ((Object)oTemp).toString() );

What Happens Here?

No matterNo matterhow youhow you

cast things,cast things,dynamicdynamic

binding takesbinding takeshold. It’shold. It’slike the like the

law of gravity.law of gravity.

Sanity CheckSanity Check

ObjectObjecttoString()

FishFish

move();toString();

AnimalAnimalint numLegs = 3String strTypetoString();move();

Object oTemp;

oTemp = animalArray[1];

Animal aTemp = (Animal) oTemp;

System.out.println (oTemp.toString());

oTemp

What if Fish had its owntoString()?

No matterNo matterhow youhow you

cast things,cast things,dynamicdynamic

binding takesbinding takeshold. It’shold. It’slike the like the

law of gravity.law of gravity.

Dynamic binding will always resolve, at run time, to themost specific version of the method. ALWAYS.ALWAYS.

““Always?”Always?”

ObjectObjecttoString()

FishFish

move();toString();

AnimalAnimalint numLegs = 3String strTypetoString();move();

Object oTemp;

oTemp = animalArray[1];

oTemp.move(); // WRONG!

oTemp

Does dynamic bindingalso work miracles?

That is, does it letyou find methods in

extending classes, if thepresent class does nothave such a method?

NO. This would cause a compile time error. Java is strongly typedstrongly typed, meaning that each time you invoke a method, the method MUST be present in the class--even if dynamic binding would later find a more specific version. So: no, dynamic binding does not trump type safety in Java.dynamic binding does not trump type safety in Java.

No suchmethod move()

in Object

if (getQuestions()) answerThem();else goodBye();