Title: Abstract Classes Introduction to Polymorphism
1Abstract Classes Introduction to Polymorphism
Lecture 26
2Abstract Classes
3Recall
- We have the ability to create hierarchies of
classes. - Good design practice suggests that we move common
methods as high as possible in the tree - Why?
- Minimize code duplication
- Minimize maintenance efforts
- Good abstraction
- Example?
4But
- What if we know that every subclass will have a
certain method but the methods will all be
different??? - What then?
- Example We are designing a calculator that will
have as a feature the ability to make
calculations involving geometric shapes - We want it to handle rectangle, squares,
triangles, equilateral triangles, ellipses and
circles - Each shape should know how to calculate its area
and perimeter
5Shapes
Shape
getArea getPerim
Ellipse
Rectangle
Triangle
major minor
altitude base
length width
6Need
- What we would like is the ability to say in the
Shape class that all Shapes will have getArea
and getPerimeter methods. - We obviously dont know what they will be when
all we know is that something is a shape but... - The basic idea is for the compiler to provide as
a service the ability to force all subclasses
of shape to have a getArea and getPerimeter
method - The underlying philosophy is simple
- Catch errors when compiling the program not when
running the program
7Abstract Methods
- We have the ability to define a method with no
method body. - We are required to label this method as abstract
- Once a class contains an abstract method it too
must be labelled abstract - Every subclass will too be abstract until a
subclass is written in which every abstract
method has been defined - Abstract classes cannot be used to make
Objects!!! - But, they can be used to make references!?!?!?
8Shape
- // Comments omitted...
- abstract class Shape
- public String name
- public Shape(String name)
- this.name name
-
- public abstract double getArea()
- public abstract double getPerim()
9Rectangle
- class Rectangle extends Shape
- private double ln
- private double wd
- public Rectangle(String name, double ln, double
wd) - super(name)
- this.ln ln
- this.wd wd
-
- public double getArea()
- return ln wd
-
- public double getPerim()
- return 2.0 (ln wd)
-
10In case youre wondering...
If Shape is abstract and ThingsWithStraightSides
doesnt define getArea then it must also be
abstract.
Shape
ThingsWithStraightSides
Triangle
Rectangle
11Questions?
12Introduction to Polymorphism
13Recall
- We set out to explore a new language, Java, which
uses the Object Oriented Paradigm. - We claimed that it would allow us to have
superior - Encapsulation
- Reusability
- Adaptability
- But as of now that may not be quite so apparent.
- The LinkedList class that we made held a linked
list of StudentRecords but to hold anything else
it will require some not insignificant amount of
modification - We need another tool to allow us to make
collections that will hold anything!
14Scenarios
- A veterinarian's algorithm might have a list of
animals, but each one needs different food or
care we want ONE information system to track all
of this without complex logic for each individual
kind of animal. - A car dealership sells many different types of
cars with different features, but each has a
price and quantity in stock. - A registration system might treat in-state
students differently from out-of-state students,
graduate students differently from
undergraduates, etc.
15Motivation
- Wed like to be able to manage objects of
different kinds of classes. - Since classes within a class hierarchy often
share common methods and attributes, wed like to
make use of this fact to make our algorithms
simpler.
16Polymorphism
- Polymorphism means many or multiple forms.
- Refers to the ability to tell an object to
perform a method without knowing exactly which
method is going to get invoked. - May initially seem somewhat magical
- Well, actually it is...
17A Class Hierarchy
Animal
Dog
Cat
Fish
18A Polymorphic Example
Animal
Dog
Dog myDog myDog new Dog() Animal
myAnimal myAnimal myDog
19Extends
- Note that when Java uses inheritance the keyword
is extends - This is because literally making a subclass
object in a sense also makes a superclass
object!!! - Huh?
- When we say
- myDog new Dog()
- the Dog constructor gets called.
- It, in turn, must call the Animal constructor
- And heres the big secret
20Everything is an Object!
- Thats right!
- There is a class Object already defined
- When you dont extend anything by default you
extend Object - Thus the Animal constructor calls the Object
constructor - Looking at an object in memory it would look
something like this
Object
reference
Dog Object
Animal
myDog
Dog
21Polymorphism Explained
- The rule is very simple
- A reference can refer to an object which is
either - The same type as the reference
- Has a superclass of the same type as the
reference - So all of the following are legal
- Dog d new Dog()
- Animal a new Animal()
- Object o new Object
Object
reference
Dog Object
Animal
Dog
22Object
Dog
Animal
Object
Dog d d new Dog()
Dog d d new Animal()
Dog d d new Object()
Object
REF
REF
REF
Animal a a new Dog()
Animal a a new Animal()
Animal a a new Object()
Object
REF
REF
REF
Reference
Object o o new Dog()
Object o o new Animal()
Object o o new Object()
Object
REF
REF
REF
Could this be some form of Matrix?
23An Illegal Example
- We are able to assign an object of a sub-class
into an object of a super-class as in - Animal MyAnimal new Dog()
- But the reverse is not true. We cant assign a
superclass object into a sub-class object. - Dog MyDog new Animal() // illegal
All dogs are animals but not all animals are dogs
24Method Calls and Polymorphism
- Assume the Dog class extends the Animal class,
redefining the makeNoise method. - Consider the following
- Animal MyAnimal new Dog()
- MyAnimal.makeNoise()
- Note The Animal reference is referring to a Dog
object. And its the Dogs makeNoise method that
gets invoked!
25Dynamic Binding
- Very simple rule.
- No matter what the reference type is, Java will
search the object and execute the lowest
occurence of a method it finds. - class Object has a toString method
- Assume that both Animal and Dog have overridden
the toString method
Object toString()
Object o
Animal a
A Dog Object
Animal toString()
Dog d
Dog toString()
o.toString() a.toString() d.toString()
26Dynamic Binding
- Very simple rule.
- No matter what the reference type is, Java will
search the object and execute the lowest
occurrence of a method it finds. - class Object has a toString method
- Even if Animal has no toString method!
Object toString()
Object o
Animal a
A Dog Object
Animal
Dog d
Dog toString()
o.toString() a.toString() d.toString()
27Polymorphism vs. Inheritance
- Inheritance is required in order to achieve
polymorphism (we must have class hierarchies). - Re-using class definitions via extension and
redefinition - Polymorphism is not required in order to achieve
inheritance. - An object of class A acts as an object of class B
(an ancestor to A).
28Processing Collections
- One of the main benefits of polymorphism is the
ability to easily process collections. - We will consider a collection (queue) of Objects
in the next example. . .
Note This means we rewrite our Queue class (and
all associated classes) to hold Objects.
29The Banking Class Hierarchy
Object
BankAccount
SavingsAccount
CheckingAccount
DeluxeSavings
NOWAccount
MoneyMarketAccount
CDAccount
30A Collection of Bank Accounts
- Imagine a bank needs to manage all of the
different types of accounts. - Rather than maintain seven separate queues, one
each for BankAccounts, SavingsAccounts,
DeluxeSavings, CDAccounts, CheckingAccounts,
NOWAccounts, and MoneyMarketAccounts - We can maintain only one queue of Objects.
31Polymorphic Banking
- // Assume accounts of various kinds
- CheckingAccount johnAaccount
- DeluxeSavings paulAccount
- CDAccount paulOtherAccount
- NOWAccount georgeAccount
- MoneyMarket ringoAccount
- // Then put them all in a single structure
- // which is a Queue which holds Objects
- Queue acctQueue
- acctQueue.enqueue(johnAccount)
- acctQueue.enqueue(paulAccount)
- acctQueue.enqueue(paulOtherAccount)
- acctQueue.enqueue(georgeAccount)
- acctQueue.enqueue(ringoAccount)
-
32Polymorphic Banking
- accountQueue is polymorphic
- It is holding accounts of many forms.
- Each of the accounts is within the family of
the class hierarchy of bank accounts. - Each one will have its own set of capabilities
via inheritance (extension, and/or redefinition).
33Example of Polymorphic Banking
- With polymorphism, our main algorithm doesnt
care what kind of account it is processing - double sum
- . . .
- sum 0.0
- while(! acctQueue.isEmpty())
- sum
- ((BankAccount)(acctQueue.dequeue())).getBalan
ce() -
- System.out.println
- (Sum of the balances is sum )
34Resolving Polymorphic Method Calls
- The Java compiler is our friend
- Since we said the Queue was a Queue which was
written to hold Objects what comes out is an
Object reference - class Object has no getBalance() method so the
compiler would give us a friendly error message
politely refuse to compile until we cast the
object to a BankAccount object - As annoying as this may seem its for our own
good! - Again, Java wants to catch as many problems at
compile time to avoid errors at run time!
35Polymorphism
- This is the magic of polymorphismit keeps
track of family members within the inheritance
hierarchy for you. - Without it, wed have lots of code sprinkled
through out our algorithm choosing among many
options - if( its a Checking_Account )
- call Checking_Account Calc_Interest
- else if( its a Super_Savings )
- call Super_Savings Calc_Interest
- else if( its a CD_Account )
- call CD_Account Calc_Interest
- else if( its a NOW_Account )
- call NOW_Account Calc_Interest
- . . .
36Summary
- Polymorphism allows objects to represent
instances of its own class and any of its
subclasses. - Polymorphic collections are useful for managing
objects since all objects are descendants of
class Object - No matter what the reference type the actual
object knows what type it is - When there is a choice dynamic binding goes to
the lowest level.
37Questions?
38Code used in Class - ONode
- class ONode
- Object data
- ONode next
- public ONode()
- this.data null
- this.next null
- // Constructor
- public ONode(Object data)
- this.data data
- this.next null
- // Constructor
- public String toString()
- if(data null)
- return "ONode null"
- else
- return "ONode " data
39Code used in Class - Queue
- class Queue
- private ONode head
- private ONode tail
- // Purpose constructor
- // Postcon head and tail references set to null
- public Queue()
- setHead(null)
- setTail(null)
-
- // PPP omitted for clarity!!!
- public void setHead(ONode h) head h
- public void setTail(ONode t) tail t
- public ONode getHead() return head
- public ONode getTail() return tail
- // Precon instantiation (or none!)
- // Purpose returns true if queue is empty
- // Postcon no change to queue
- public boolean isEmpty()
- return (getHead() null)
40Code used in Class - Queue
- // Queue continued
- // Precon instantiation
- // Purpose remove element from head of queue
- // Postcon If queue was empty no
change returns 0 - // If queue non-empty returns head
- public Object Dequeue()
- Object retVal
- if(isEmpty())
- retVal null
-
- else
- retVal getHead().data
- setHead(getHead().next)
- if(getHead() null)
- setTail(null)
-
- return retVal
- // Dequeue
41Code used in Class - StudentRecord
- class StudentRecord
- public String name
- public double gpa
- public int ssn
- public StudentRecord(String n, double g, int s)
- name n
- gpa g
- ssn s
-
- // Precon fields should be initialized
- // Purpose return string representation
- // Postcon no change to StudentRecord
- public String toString()
- String retVal
- retVal name " "
- retVal gpa " "
- retVal ssn
- return retVal
42Code used in Class - Account
- abstract class Account
- private double balance
- public int number
- public String owner
- public Account(String o, int n )
- owner o
- number n
- setBalance(0)
- // constructor
- public void setBalance(double balance)
- this.balance balance
- System.out.println( owner "'s acct " number
- " new balance now " getBalance())
-
-
- public double getBalance()
43Code used in Class - BankAccount
- class BankAccount extends Account
- public BankAccount( String o, int n )
- super( o, n )
- // constructor
- public double calcInterest()
- return 0.0
-
- public static void main( String argv )
- BankAccount b new BankAccount("John", 1)
- b.deposit(100)
- b.withdraw(50)
- b.withdraw(200)
-
- // BankAccount
44Code used in Class - SavingsAccount
- class SavingsAccount extends Account
- public final static double RATE 0.023
- public final static double MIN_BALANCE 500.00
- public SavingsAccount( String name, int num )
- super( name, num )
-
- public double calcInterest()
- double interest
- if (getBalance() gt MIN_BALANCE)
- interest getBalance()RATE
- else
- interest 0.00
- return interest
-
- public static void main( String argv )
45Code used in Class - DeluxeSavings
- class DeluxeSavings extends SavingsAccount
- private boolean overdraftOK
- public final static double OVERDRAFTCHARGE
20.0 - public DeluxeSavings(String nm, int num )
- super(nm, num)
- setOverdraftOK(false)
-
- public void setOverdraftOK(boolean odok)
- overdraftOK odok
- public void withdraw(double amt)
- if (overdraftOK)
- setBalance(getBalance() - amt)
- if (getBalance() lt 0)
- setBalance(getBalance() -
OVERDRAFTCHARGE) - else
- super.withdraw(amt)
46Code used in Class - Teller
- class Teller
- public static void main( String argv )
- Queue tq new Queue()
- BankAccount john new BankAccount("John", 1)
- SavingsAccount paul new SavingsAccount("Paul",
2) - DeluxeSavings george new DeluxeSavings("George
", 3) - SavingsAccount ringo new SavingsAccount("Ringo
", 4) - tq.Enqueue(john)
- tq.Enqueue(paul)
- tq.Enqueue(george)
- tq.Enqueue(ringo)
- john.deposit(100)
- paul.deposit(1000)
- paul.deposit(paul.calcInterest())
- paul.withdraw(700)
- paul.deposit(paul.calcInterest())
- george.deposit(1000)
- george.deposit(george.calcInterest())
47(No Transcript)