Title: Adas subtype'
1Inheritance
- Adas subtype.
- subtype Small_int is integer range -100..100
- subtype Age is integer range 0..150
- All operations of integer are inherited by
Small_int. - Enhance software reuse-application written for
(old) base class can be reused by (new) derived
classes. - Extensibility-new classes can be added without
affecting existing classes. - Flexibility-polymorphism.
2Yet Another Employee Example
Employee
- Our goal is to describe a special kind of
Employee, called Manager. - Employee is the based class.
- Manager is the derived class.
- Manager inherits all the public and protected
properties of Employee. - Protected/Friendly
- Public for derived classes friends in the same
packate - Private for others
name String
salary Double
hireDate Date
Employee()
getName()
getSalary()
getHireDay()
raiseSalary()
Manager
bonus Double
Manager()
getSalary()
setBonus()
3Rational Rose Screen Shot
- What does inheriting properties mean?
- It means that the properties (methods and
instance variables) are now accessible to the
derived class. - Since the instance variables in Employee are all
private, they are inherited but not visible.
4Instance Variables
5Definition of Employee
- class Employee
- public Employee(String n, double s, int year,
int month, int day) - name n
- salary s
- GregorianCalendar calendar
- new GregorianCalendar(year, month - 1,
day) - // GregorianCalendar uses 0 for January
- hireDay calendar.getTime()
-
- public String getName()
- return name
- public double getSalary()
- return salary
- public Date getHireDay()
- return hireDay
- public void raiseSalary(double byPercent)
6Definition of Manager
class Manager extends Employee /
_at_param n the employee's name _at_param s the
salary _at_param year the hire year
_at_param month the hire month _at_param day the
hire day / public Manager(String n, double
s, int year, int month, int day)
super(n, s, year, month, day) bonus
0 public double getSalary()
double baseSalary super.getSalary()
return baseSalary bonus public void
setBonus(double b) bonus b
private double bonus
7Driver
- import java.util.
- public class ManagerTest
- public static void main(String args)
- // construct a Manager object
- Manager boss new Manager("Carl Cracker",
80000, - 1987, 12, 15)
- boss.setBonus(5000)
- Employee staff new Employee3
- // fill the staff array with Manager and
Employee objects - staff0 boss
- staff1 new Employee("Harry Hacker",
50000, - 1989, 10, 1)
- staff2 new Employee("Tommy Tester",
40000, - 1990, 3, 15)
- // print out information about all Employee
objects
8Outputs
- nameCarl Cracker,salary85000.0
- nameHarry Hacker,salary50000.0
- nameTommy Tester,salary40000.0
9Generalization vs. Specilization
Employee
- Up an inheritance hierarchy More generalized
with common properties. - Down an inheritance hierarchy More specialized
with specific properties.
name String
salary Double
hireDate Date
Employee()
getName()
getSalary()
getHireDay()
raiseSalary()
Manager
bonus Double
Manager()
getSalary()
setBonus()
10A more Complicated Employee Example
11Employee
- public abstract class Employee
- private String firstName
- private String lastName
- // Constructor
- public Employee( String first, String last )
-
- firstName first
- lastName last
-
-
- // Return the first name
- public String getFirstName() return
firstName - // Return the last name
- public String getLastName() return lastName
- public String toString()
- return firstName ' ' lastName
12Boss
- public final class Boss extends Employee
- private double weeklySalary
- // Constructor for class Boss
- public Boss( String first, String last, double
s) -
- super( first, last ) // call superclass
constructor - setWeeklySalary( s )
-
-
- // Set the Boss's salary
- public void setWeeklySalary( double s )
- weeklySalary ( s gt 0 ? s 0 )
-
- // Get the Boss's pay
- public double earnings() return
weeklySalary -
- // Print the Boss's name
- public String toString()
13CommissionWorker
- public final class CommissionWorker extends
Employee - private double salary // base salary per
week - private double commission // amount per item
sold - private int quantity // total items
sold for week - // Constructor for class CommissionWorker
- public CommissionWorker( String first, String
last, - double s, double c,
int q) -
- super( first, last ) // call superclass
constructor - setSalary( s )
- setCommission( c )
- setQuantity( q )
-
-
- // Set CommissionWorker's weekly base salary
- public void setSalary( double s )
- salary ( s gt 0 ? s 0 )
-
14CommissionWorker (cont.)
- // Set CommissionWorker's commission
- public void setCommission( double c )
- commission ( c gt 0 ? c 0 )
-
- // Set CommissionWorker's quantity sold
- public void setQuantity( int q )
- quantity ( q gt 0 ? q 0 )
-
- // Determine CommissionWorker's earnings
- public double earnings()
- return salary commission quantity
-
- // Print the CommissionWorker's name
- public String toString()
- return "Commission worker "
super.toString() -
-
15PieceWorker
- public final class PieceWorker extends Employee
- private double wagePerPiece // wage per piece
output - private int quantity // output for
week - public PieceWorker( String first, String last,
double w, int q ) -
- super( first, last ) // call superclass
constructor - setWage( w )
- setQuantity( q )
-
-
- // Set the wage
- public void setWage( double w )
- wagePerPiece ( w gt 0 ? w 0 )
-
- // Set the number of items output
- public void setQuantity( int q )
- quantity ( q gt 0 ? q 0 )
-
16HourlyWorker
- public final class HourlyWorker extends Employee
- private double wage // wage per hour
- private double hours // hours worked for
week - public HourlyWorker( String first, String
last, double w, double h ) - super( first, last ) // call superclass
constructor - setWage( w )
- setHours( h )
-
-
- public void setWage( double w )
- wage ( w gt 0 ? w 0 )
-
- public void setHours( double h )
- hours ( h gt 0 h lt 168 ? h 0 )
-
- public double earnings() return wage
hours -
- public String toString()
17Driver
import java.text.DecimalFormat public class
EmployeeTest public static void main(String
args) Employee ref // superclass
reference Boss bnew Boss( "John",
"Smith", 800.00 ) CommissionWorker
cnew CommissionWorker( "Sue", "Jones", 400.0,
3.0, 150) PieceWorker pnew PieceWorker(
"Bob", "Lewis", 2.5, 200 ) HourlyWorker
hnew HourlyWorker( "Karen", "Price", 13.75, 40
) DecimalFormat precision2 new
DecimalFormat( "0.00" ) ref b
// superclass reference to subclass object
System.out.println( ref.toString() " earned "
precision2.format( ref.earnings() ))
System.out.println( b.toString() " earned "
precision2.format( b.earnings() ))
ref c // superclass reference to subclass
object System.out.println( ref.toString()
" earned " precision2.format(
ref.earnings() )) System.out.println(
c.toString() " earned " precision2.format(
c.earnings() )) ref p //
superclass reference to subclass object
System.out.println( ref.toString() " earned "
precision2.format( ref.earnings() ))
System.out.println( p.toString() " earned "
precision2.format( p.earnings() ))
ref h // superclass reference to subclass
object System.out.println( ref.toString()
" earned " precision2.format( ref.earnings()
)) System.out.println( h.toString() "
earned " precision2.format( h.earnings() ))
18Outputs
- Boss John Smith earned 800.00
- Boss John Smith earned 800.00
- Commission worker Sue Jones earned 850.00
- Commission worker Sue Jones earned 850.00
- Piece worker Bob Lewis earned 500.00
- Piece worker Bob Lewis earned 500.00
- Hourly worker Karen Price earned 550.00
- Hourly worker Karen Price earned 550.00
19Remarks
- When a superclass abstract method got overridden
by its subclass (with the same signature), then
the compiler to delay the binding between the
function call and the function implementation
until run-time (dynamic or lazy binding). Hence,
the polymorphic behavior is achieved. - A polymorphic function implies that objects of
different but similar can be manipulated using
the same interface. The advantages are backward
compatibility, extensibility, and software reuse. - Abstract methods can be used when
- we want to capture common behaviors in the
derived classes, and - the common behaviors are too general to warrant
any specific implementation at the base class. - Class with any abstract method must be an
abstract class.
20Account Example
21BankAccount
public class BankAccount public BankAccount()
balance 0 public
BankAccount(double initialBalance) balance
initialBalance public void
deposit(double amount) balance balance
amount public void withdraw(double
amount) balance balance - amount
public double getBalance() return
balance public void
transfer(BankAccount other, double amount)
withdraw(amount) other.deposit(amount)
private double balance
22SavingsAccount
public class SavingsAccount extends BankAccount
public SavingsAccount(double rate)
interestRate rate public void
addInterest() double interest
getBalance() interestRate / 100
deposit(interest) private double
interestRate
23CheckingAccount
public class CheckingAccount extends
BankAccount public CheckingAccount(int
initialBalance) // construct superclass
super(initialBalance) //
initialize transaction count
transactionCount 0 public void
deposit(double amount) transactionCount
// now add amount to balance
super.deposit(amount) public void
withdraw(double amount) transactionCount
// now subtract amount from balance
super.withdraw(amount)
public void deductFees() if
(transactionCount gt FREE_TRANSACTIONS)
double fees TRANSACTION_FEE
(transactionCount - FREE_TRANSACTIONS)
super.withdraw(fees)
transactionCount 0 private int
transactionCount private static final int
FREE_TRANSACTIONS 3 private static final
double TRANSACTION_FEE 2.0
24TimeDepositAccount
public class TimeDepositAccount extends
SavingsAccount public TimeDepositAccount(double
rate, int maturity) super(rate)
periodsToMaturity maturity public
void addInterest() periodsToMaturity--
super.addInterest() public void
withdraw(double amount) if
(periodsToMaturity gt 0)
super.withdraw(EARLY_WITHDRAWAL_PENALTY)
super.withdraw(amount) private int
periodsToMaturity private static double
EARLY_WITHDRAWAL_PENALTY 20
25Driver
public class AccountTest public static void
main(String args) SavingsAccount
momsSavings new SavingsAccount(0.5)
TimeDepositAccount collegeFund
new TimeDepositAccount(1, 3)
CheckingAccount harrysChecking new
CheckingAccount(0)
momsSavings.deposit(10000)
collegeFund.deposit(10000)
momsSavings.transfer(harrysChecking, 2000)
collegeFund.transfer(harrysChecking, 980)
harrysChecking.withdraw(500)
harrysChecking.withdraw(80)
harrysChecking.withdraw(400)
endOfMonth(momsSavings) endOfMonth(collegeF
und) endOfMonth(harrysChecking)
printBalance("mom's savings", momsSavings)
// 10000 - 2000 0.5 interest 8040
printBalance("the college fund", collegeFund)
// 10000 - 980 - 20 penalty 1
interest // 9090
printBalance("Harry's checking",
harrysChecking) // 2000 980 - 500
- 80 - 400 - 4 fees // 1996
public static void endOfMonth(SavingsAccount
savings) savings.addInterest()
public static void endOfMonth(CheckingAccount
checking) checking.deductFees()
public static void printBalance(String name,
BankAccount account) System.out.println("T
he balance of " name " account is "
account.getBalance())
26Outputs
The balance of mom's savings account is
8040.0 The balance of the college fund account
is 9090.0 The balance of Harry's checking
account is 1996.0
Exercise
Draw an inheritance diagram that shows the
inheritance relationships between the
classesPersonEmployeeStudentInstructorClass
roomObject
27Exercise
- In an OO traffic simulation system, we have the
following classes - Vehicle
- Car
- Truck
- Sedan
- Coupe
- PickupTruck
- SportUtilityVehicle
- Minivan
- Bicycle
- Motorcycle
- Draw an inheritance diagram that shows the
inheritance relationships between the classes
28Exercise
Consider using the following Card class as a
superclass to implement a hierarchy of related
classes Class Data IDcard ID number Calling
Card Card number, PIN DriverLicense Expiration
year class Card public Card() name
"" public Card(String n) name
n public boolean isExpired()
return false public void print()
System.out.println("Card holder " name)
private String name Write definitions for
each of the subclasses. For each subclass, supply
private instance variables. Leave the bodies of
the constructors and the print methods blank for
now.
29IDCard
public class IDCard extends Card public
IDCard() ID public IDCard(String n,
String i) super(n) id i private
String id
30CallingCard
public class CallingCard extends Card public
CallingCard() cardNum0 pin0 public
CallingCard(String n, long c, short
p) super(n) cardNumc pinp private
long cardNum private short pin
31DriverLicense
public class DriverLicense extends
IDCard public DriverLicense() expirationYear
0 public DriverLicense(String n, String i,
short yr) super(n, i) expirationYearyr
private short expirationYear
32Exercise
- Implement constructors for each of the three
subclasses. Each constructor needs to call the
superclass constructor to set the name. - Supply the implementation of the print method for
the three subclasses. The subclass methods need
to call the superclass print method to print the
name of the cardholder. - The Card superclass defines a method isExpired
which always returns false. This method is
appropriate for the ID card and the phone card
because those cards don't expire. But it is not
appropriate for the driver license. Supply a
method DriverLicense.isExpired() that checks if
the driver license is already expired (i.e. the
expiration year is less than the current year). - Note that you should not redefine isExpired for
the other card types. They simply inherit the
superclass method.
33Shadowing
- When a method f() in a class, say B, is
overriding a method in Bs superclass A. A.f()
becomes invisible to Bs derived classes via
inheritance. - The same rule applies for instance variables.
class Base public Base(Base rhs) public
Base() public void f()System.out.println("f()
in Base.") class Derived1 extends
Base public void f()System.out.println("f() in
Derived1.") class Derived2 extends
Derived1 public void g()f() //f() in
Derived1
34Driver
- public class Shadow
- public static void main(String args)
- Derived2 d2 new Derived2()
- Base b d2
- b.f() //f() in Derived1, dynamic binding
- d2.f() //f() in Derived1, static binding
- ((Base) d2).f() //f() in Derived1, dynamic
binding - (new Base(d2)).f() //f() in Base but...not the
same object -
-
35Final Methods
- Final methods are similar to inline functions in
C. The function body of a final method is
inlined into the source code (wherever there is
a call to that function). - Thus, final methods methods can not be overridden
in a derived class since polymorphism is not
possible anymore. - Static methods and private methods are implicitly
final. (But the reverse is not true! A final
method can still be called via a derived class
variable.)
36Example
public class FinalMethod public static void
main(String args) Derived2 d2 new
Derived2() d2.f() //f() is visible, static
binding Derived1 d1 new Derived1() d1.f()
//static binding Base b d1 //b new
Base() b.f() //dynamic binding class
Base public void f()System.out.println("f() in
Base.") class Derived1 extends Base public
final void f()System.out.println("f() in
Derived1.") class Derived2 extends
Derived1 public void g()f() //f() is
visible but... //public final void
f()System.out.println("f() in Derived 2.")
37Overriding vs. Overloading
public class Over public static void
main(String args) Derived1 d1 new
Derived1() Base b d1 b.f() b.f(10) d1.f(
) d1.f(10) class Base public void
f()System.out.println("f() in Base.") class
Derived1 extends Base public void
f()System.out.println("f() in Derived1.")
public void f(int i)System.out.println("f(int)
in Derived1"i)
38OO Design Guidelines
- General Guidelines
- Look for nouns and names in the specs., those are
usually objects or classes. - Look for verbs in the specs., those are usually
methods.
Inheritance Design Guidelines
- Trying to implement is-a relationship.
- If there is an instance variable in the
superclass that does not fit the derived class,
do not use inheritance. - If there is a method in the superclass that does
not make sense for derived class, do not use
inheritance. - If the application code is relying on the types
or classes of the object (with nested
if-then-else or switch statements), use
inheritance. - When you see a need for upcasting, use
inheritance.
39Examples
40Inheritance Design Guidelines
- Once you decided on using inheritance, these are
the steps you may go through - Starts with base class interface for the services
that all derived classes will provide-use all
abstract methods. - Determining commonly required data
- Use private instance variables with, if possible,
protected accessor methods. - Provide constructors for derived classes to
initialize the instance variables.
41Inheritance Design Guidelines
- Determining Identically Implemented Methods
- If some overridden methods have the same
implementations in the derived classes, change
the abstract methods to concrete methods. - Determining methods that have fixed
implementation and make them final. - Thus, the derived classes are inheriting
- Common data.
- Specification of methods-abstract methods
- Default implementation of methods-overriden
methods for polymorphism - Fixed implementation of methods-methods that are
final or not overridden.
42Inheritance vs. Composition
- Composition is for implementing part-of
relationships. - Composition should be chosen over inheritance
wherever possible. (When youre not sure, use
composition.) - Someone would argue that inheritance is also a
mechanism for building up things-adding wheels
and motor to a car. But this is causing
unnecessary overhead and misleading meaning.
43Inheritance vs. Composition
- Given a Stack of Object and String.
- We want a StringStack class.
- Inheritance or composition?
- Shape, point, circle, cylinder, square, cube.
44Shapes
public class Point extends Shape private int
x, y // coordinates of the Point //
no-argument constructor public Point()
setPoint( 0, 0 ) // constructor public
Point( int a, int b ) setPoint( a, b )
// Set x and y coordinates of Point public
void setPoint( int a, int b ) x a y
b // get x coordinate public int
getX() return x // get y coordinate
public int getY() return y // convert
the point into a String representation public
String toString() return "" x ", "
y "" // return the class name
public String getName() return "Point"
public abstract class Shape public double
area() return 0.0 public double volume()
return 0.0 public abstract String
getName()
45Shapes
public class Circle extends Point // inherits
from Point private double radius //
no-argument constructor public Circle()
// implicit call to superclass constructor
here setRadius( 0 ) //
Constructor public Circle( double r, int a,
int b ) super( a, b ) // call the
superclass constructor setRadius( r )
// Set radius of Circle public void
setRadius( double r ) radius ( r gt 0 ?
r 0 )
// Get radius of Circle public double
getRadius() return radius // Calculate
area of Circle public double area() return
Math.PI radius radius // convert the
Circle to a String public String toString()
return "Center " super.toString()
" Radius " radius //
return the class name public String getName()
return "Circle"
46Shapes
- public class Cylinder extends Circle
- private double height // height of Cylinder
-
- // no-argument constructor
- public Cylinder()
-
- // implicit call to superclass constructor
here - setHeight( 0 )
-
- // constructor
- public Cylinder( double h, double r, int a,
int b ) -
- super( r, a, b ) // call superclass
constructor - setHeight( h )
-
- // Set height of Cylinder
- public void setHeight( double h )
// Get height of Cylinder public double
getHeight() return height // Calculate
area of Cylinder (i.e., surface area) public
double area() return 2 super.area()
2 Math.PI getRadius()
height // Calculate volume of
Cylinder public double volume() return
super.area() height // Convert a
Cylinder to a String public String toString()
return super.toString() " Height "
height // Return the class name public
String getName() return "Cylinder"
47Remarks
- In theory, users do not need to see the source
code of classes from which they inherit. In
practice, people who license classes usually find
that the customers often demand the source code.
Programmers still seem reluctant to incorporate
code into their programs when this code has been
written by other people. - When performance is a major concern, programmers
may want to see source code of classes they are
inheriting from so they can tune the code to meet
their performance requirements. - Creating a derived class does not affect its base
classs source code or object code the integrity
of a base class is preserved by inheritance. - In an OO system, classes are often closely
related. Factor out common attributes and
behaviors and place them in a base class. Then
use inheritance to form derived classes. - A few super classes with rich functionality
discourage software reuse. - A large collection of smaller classes makes it
hard for the user to find the right class.
(Class proliferation) - If classes produced through inheritance are
larger than they need to be, memory and
processing resources may be wasted. Inherit from
the class closest to what you need.
48Protected Instance Variables
- Protected instance variables are visible to all
derived class. Thus, any user can gain access to
a class protected section by inheritance. - Thats why private instance variables are
preferred over protected ones. However,
protected methods are desirable.
public class Base // protected int
i public class Outsider1 public void f()
Base b new Base() b.i 0 //b.i not
visible //... public class Outsider2
extends Base public void g() Base b new
Base() b.i 0 //now weve gained
access!
49Objects Creation Initialization Order
- Recall within a class, the initialization order
is class variable initializer, static
initialization block, instance variable
initializer, initialization block, constructor
body. - In an inheritance hierarchy, the order of
constructor calls for a complex object is as
follows - The base-class constructor is called. This step
is repeated recursively such that the root of the
hierarchy is constructed first, followed by the
next-derived class, etc., until the most-derived
class is reached. - Member initializers are called in the order of
declaration. - The body of the derived-class constructor is
called.
50Example
class Meal Meal() System.out.println("Meal(
)") class Lunch extends Meal Lunch()
System.out.println("Lunch()") class
PortableLunch extends Lunch PortableLunch()
System.out.println("PortableLunch()") cl
ass Sandwich extends PortableLunch private
Bread b new Bread() private Cheese c new
Cheese() private Lettuce l new Lettuce()
Sandwich() System.out.println("Sandwic
h()") public static void main(String
args) new Sandwich()
class Bread Bread() System.out.println("Bre
ad()") class Cheese Cheese()
System.out.println("Cheese()") class
Lettuce Lettuce() System.out.println("Lettu
ce()")
Outputs Meal() Lunch() PortableLunch() Bread() C
heese() Lettuce() Sandwich()
51What if a base class constructor calls a derived
class function?
abstract class Base Base() f() public
abstract void f() class Derived extends Base
public void f() System.out.println(is)
private int i100 private String
s"ABC" public class Initialize public
static void main(String args) Derived d
new Derived()
1. The storage allocated for the object is
initialized to binary zero before anything else
happens. 2. The base-class constructors are
called as described previously. At this point,
the overridden f( ) method is called, (before the
Base constructor is called), which discovers an i
value of zero and s value of null, due to step
one. 3. Member initializers are called in the
order of declaration. 4. The body of the
derived-class constructor is called.
52Upcasting Downcasting Revisited
- Consider the shape, point, circle, cylinder
example Point p Circle c - p c //legal, Circle is a kind of Point
- p.getRadius() //illegal, extra capability n/a
- c p //downcasting, illegal
- c (Circle) p //legal at compile time
- c.getRadius() //run-time check needed