Transcript Lecture 8
Lecture 8
Inheritance
Instructors:
Fu-Chiung Cheng
(鄭福炯)
Associate Professor
Computer Science & Engineering
Tatung Institute of Technology
1
Outline
• the concept of inheritance
• the protected modifier
• adding and modifying methods through inheritance
• creating class hierarchies
1
Inheritance
• Inheritance allows a software developer to derive
a new class from an existing one
• The existing class is called the parent class, or
superclass, or base class
• The derived class is called the child class or
subclass.
• The child class inherits characteristics (data &
methods) of the parent class
2
Inheritance
• Inheritance relationships:
Vehicle
– base class: Vehicle
– derived class: Car
– Car inherits data & methods
Car
from Vehicle
• Inheritance creates an is-a relationship, meaning
the child is-a more specific version of the parent
3
Deriving Subclasses
• The reserved word extends is used to establish
an inheritance relationship
class Car extends Vehicle {
// class contents
}
• See Words.java
4
class Book {
protected int pages = 1500;
public void pageMessage () {
System.out.println ("Number of pages: " + pages);
} // method pageMessage
} //
class Dictionary extends Book {
private int definitions = 52500;
public void definitionMessage () {
System.out.println ("Number of definitions: "+definitions);
System.out.println ("Definitions per page: “
+definitions/pages);
} // method definitionMessage
} // class Dictionary
class Words { // Test Driver
public static void main (String[] args) {
Dictionary webster = new Dictionary ();
webster.pageMessage();
webster.definitionMessage();
} } // class Words
The protected Modifier
• The visibility modifiers determine which class
members get inherited and which do not
• Variables and methods declared with public
visibility are inherited, and those with private
visibility are not
• Note that public variables violate our goal of
encapsulation
• The protected visibility modifier allows a
member to be inherited, but provides more
protection than public does
5
The super Reference
• Constructors are not inherited, even though they
have public visibility
• Yet we often want to use the parent's constructor
to set up the "parent's part" of the object
• The super reference can be used to refer to the
parent class, and is often used to invoke the
parent's constructor
• See Words2.java
6
class Book {
protected int pages;
public Book (int numPages) { pages = numPages; }
public void pageMessage () {
System.out.println ("Number of pages: " + pages); }
} // class Book
class Dictionary extends Book {
private int definitions;
public Dictionary (int numPages, int numDefinitions) {
super (numPages);
definitions = numDefinitions;
} // constructor Dictionary
public void definitionMessage () {
System.out.println ("Number of definitions: " + definitions)
System.out.println ("Definitions per page: “
+definitions/pages);
} // method definitionMessage
} // class Dictionary
class Words2 {
public static void main (String[] args) {
Dictionary webster = new Dictionary (1500, 52500);
webster.pageMessage();
webster.definitionMessage();
System.out.println(webster); // try println object
} // method main
} // class Words2
Defined vs. Inherited
• A subtle feature of inheritance is the fact that even
if a method or variable is not inherited by a child,
it is still defined for that child
• An inherited member can be referenced directly in
the child class, as if it were declared in the child
class
• But even members that are not inherited exist for
the child, and can be referenced indirectly through
parent methods
• See Eating.java and School.java
7
class Food {
final private int CALORIESPERGRAM = 9;
private int fat;
protected int servings;
public Food (int numFatGrams, int numServings) {
fat = numFatGrams;
servings = numServings;
} // constructor Food
private int calories() { return fat * CALORIESPERGRAM; }
public int caloriesPerServing() {
return (calories() / servings); }
} // class Food
class Pizza extends Food {
public Pizza (int amountFat) { super (amountFat, 8); }
} // class Pizza
// main test driver
Pizza special = new Pizza (275);
System.out.println ("Calories per serving: " +
class Food {
final private int CALORIESPERGRAM = 9;
private int fat;
protected int servings;
public Food (int numFatGrams, int numServings) {
fat = numFatGrams;
servings = numServings;
} // constructor Food
private int calories() { return fat * CALORIESPERGRAM; }
public int caloriesPerServing() { return (calories() / servings
} // class Food
class Pizza extends Food {
public Pizza (int amountFat) { super (amountFat, 8); }
} // class Pizza
// main test driver
Pizza special = new Pizza (275);
System.out.println ("Calories per serving: " +
special.caloriesPerServing());
class Student {
protected String name;
protected int numCourses;
public Student (String studentName, int classes) {
name = studentName;
numCourses = classes;
} // constructor Student
public void info () {
System.out.println ("Student name: " + name);
System.out.println ("Number of courses: " +
numCourses);
} // method info
public static void main(String[] argv) {
System.out.println("Student Main"); }
} // class Student
class GradStudent extends Student {
private String source;
private double rate;
public GradStudent (String studentName, int classes
String supportSource, double hourlyRate) {
super (studentName, classes);
source = supportSource;
rate = hourlyRate;
} // constructor GradStudent
public void support () {
System.out.println ("Support source: " + source);
System.out.println ("Hourly pay rate: " + rate);
} // method support
} // class GradStudent
class School {
public static void main (String[] args) {
Student sammy = new Student ("Sammy", 5);
GradStudent pete = new GradStudent ("Pete", 3,
"Teaching Assistant", 8.75);
sammy.info();
System.out.println();
pete.info();
pete.support();
} // method main
} // class School
Overriding Methods
• A child class can override the definition of an
inherited method in favor of its own
• A child can redefine a method it inherits from its
parent
• Overriding method:
– has the same signature as the parent's method
– has different code in the body
• The object type determines which method is
invoked
• See Messages.java
8
class MyMessages {
public static void main (String[] args) {
Thought parked = new Thought();
Advice dates = new Advice();
parked.message();
dates.message();
}
} // class Messages
class Thought {
public void message() {
System.out.println (”Message");
}
} // class Thought
class Advice extends Thought {
public void message() { // overriding method
System.out.println (”Advice.");
} // method message
} // class Advice
Overloading vs. Overriding
• Don't confuse the concepts of overloading and overriding
• Overloading deals with multiple methods in the same
class with the same name but different signatures
• Overriding deals with two methods, one in a parent class
and one in a child class, that have the same signature
• Overloading lets you define a similar operation in
different ways for different data
• Overriding lets you define a similar operation in different
ways for different object types
9
The super Reference Revisited
• The super reference can be used to invoke any
method from the parent class
• This ability is often helpful when using overridden
methods
• The syntax is:
super.method(parameters)
• See Firm.java
10
class Firm {
public static void main (String[] args) {
Executive sam = new Executive ("Sam", "123 Main Line",
"555-0469", "123-45-6789", 1923.07);
Employee carla = new Employee ("Carla", "456 Off Line",
"555-0101", "987-65-4321", 846.15);
Employee woody = new Employee ("Woody",
"789 Off Rocker", "555-0000", "010-20-3040", 769.23);
woody.print();
System.out.println ("Paid: " + woody.pay());
System.out.println();
carla.print();
System.out.println ("Paid: " + carla.pay());
System.out.println();
sam.print();
sam.awardBonus (2000);
System.out.println ("Paid: " + sam.pay());
System.out.println(); } } // class Firm
class Employee {
protected String name;
protected String address;
protected String phoneNumber;
protected String socialSecurityNumber;
protected double payRate;
public Employee (String empName, String empAddress,
String empPhone,String empSsnumber, double empRate) {
name = empName;
address = empAddress;
phoneNumber = empPhone;
payRate = empRate;
socialSecurityNumber = empSsnumber;
} // constructor Employee
public double pay () { return payRate; } // method pay
public void print () {
System.out.println (name + " " + socialSecurityNumber);
System.out.println (address);
System.out.println (phoneNumber);
} } // class Employee
class Executive extends Employee {
private double bonus;
public Executive (String execName, String execAddress,
String execPhone, String execSsnumber,
double execRate) {
super (execName, execAddress, execPhone,
execSsnumber, execRate); // call parent’s constructor
bonus = 0; // bonus yet to be awarded
} // constructor Executive
public void awardBonus (double execBonus) {
bonus = execBonus;
} // method awardBonus
public double pay () {
double paycheck = super.pay() + bonus; // call parent’s method
bonus = 0;
return paycheck;
} // method pay
} // class Executive
Class Hierarchies
• A child class of one parent can be the parent of
another child, forming class hierarchies:
Business
RetailBusiness
Macy's
K-Mart
ServiceBusiness
Kinko's
11
Class Hierarchies
• Two children of the same parent are called siblings
• Good class design puts all common features as
high in the hierarchy as is reasonable
• Class hierarchies often have to be extended and
modified to keep up with changing needs
• There is no single class hierarchy that is
appropriate for all situations
• See Accounts2.java
12
class Accounts2 {
public static void main (String[] args) {
SavingsAccount savings =
new SavingsAccount (4321, 5028.45, 0.02);
BonusSaverAccount bigSavings =
new BonusSaverAccount (6543, 1475.85, 0.02);
CheckingAccount checking =
new CheckingAccount (9876, 269.93, savings);
savings.deposit (148.04);
bigSavings.deposit (41.52);
savings.withdrawal (725.55);
bigSavings.withdrawal (120.38);
checking.withdrawal (320.18);
} // method main
} // class Accounts2
class BankAccount {
protected int account; protected double balance;
public BankAccount (int accountNum, double initialBalance) {
account = accountNum;
balance = initialBalance; }
public void deposit (double amount) {
balance += amount;
System.out.println ("Deposit into account " + account);
System.out.println ("Amount: " + amount);
System.out.println ("New balance: " + balance);
System.out.println (); } // method deposit
public boolean withdrawal (double amount) {
boolean result = false;
System.out.println ("Withdrawl from account " + account);
System.out.println ("Amount: " + amount);
if (amount > balance)
System.out.println ("Insufficient funds.");
else { balance -= amount;
System.out.println ("New balance: " + balance);
result = true; }
return result; } } // class BankAccount
class CheckingAccount extends BankAccount {
private SavingsAccount overdraft;
public CheckingAccount (int accountNum,
double initialBalance, SavingsAccount protection) {
super (accountNum, initialBalance);
overdraft = protection; } // constructor CheckingAccount
public boolean withdrawal (double amount) {
boolean result = false;
if ( ! super.withdrawal (amount) ) {
System.out.println ("Using overdraft...");
if ( ! overdraft.withdrawal (amount-balance) )
System.out.println ("Overdraft source insufficient.");
else {
balance = 0;
System.out.println ("New balance on account " +
account + ": " + balance);
result = true;
}
}
return result; } } // class CheckingAccount
class SavingsAccount extends BankAccount {
protected double rate;
public SavingsAccount (int accountNum,
double initialBalance, double interestRate) {
super (accountNum, initialBalance);
rate = interestRate;
} // constructor SavingsAccount
public void addInterest () {
balance += balance * rate;
System.out.println ("Interest added to account: "
+ account);
System.out.println ("New balance: " + balance);
System.out.println();
} // method addInterest
} // class SavingsAccount
class BonusSaverAccount extends SavingsAccount {
private final int PENALTY = 25;
private final double BONUSRATE = 0.03;
public BonusSaverAccount (int accountNum,
double initialBalance, double interestRate) {
super (accountNum, initialBalance, interestRate);
} // constructor SuperSaverAccount
public boolean withdrawal (double amount) {
System.out.println ("Penalty incurred: " + PENALTY);
return super.withdrawal (amount+PENALTY);
} // method withdrawal
public void addInterest () {
balance += balance * (rate + BONUSRATE);
System.out.println ("Interest added to account: "+account);
System.out.println ("New balance: " + balance);
System.out.println();
} // method addInterest
The Object Class
• All objects are derived from the Object class
• If a class is not explicitly defined to be the child of
an existing class, it is assumed to be the child of
the Object class
• The Object class is therefore the ultimate root of
all class hierarchies
• The Object class contains a few useful methods,
such as toString(), which are inherited by all
classes
• See TestToString.java
13
import java.awt.Point;
class TestToString {
public static void main (String[] args) {
Integer num = new Integer (25);
Point origin = new Point (0, 0);
AnyClass myClass = new AnyClass();
String numString = num.toString();
String pointString = origin.toString();
String classString = myClass.toString();
System.out.println (numString);
System.out.println (pointString);
System.out.println (classString);
} // method main
} // class TestToString
class AnyClass {
public String toString() {
return "I am AnyClass"; } // method toString
} // class AnyClass
References and Inheritance
• An object reference can refer to an object of its
class, or to an object of any class related to it by
inheritance
• For example, if the Holiday class is used to
derive a child class called Christmas, then a
Holiday reference could actually be used to
point to a Christmas object:
Holiday day;
day = new Christmas();
14
References and Inheritance
• Assigning a predecessor object to an ancestor
reference is considered to be a widening
conversion, and can be performed by simple
assignment
• Assigning an ancestor object to a predecessor
reference can also be done, but it is considered to
be a narrowing conversion and must be done with
a cast
• The widening conversion is the most useful
15
Polymorphism
• A polymorphic reference is one which can refer to
one of several possible methods
• Suppose the Holiday class has a method called
celebrate, and the Christmas class
overrode it
• Now consider the following invocation:
day.celebrate();
• If day refers to a Holiday object, it invokes
Holiday's version of celebrate; if it refers
to a Christmas object, it invokes that version 16
Polymorphism
• In general, it is the type of the object being
referenced, not the reference type, that determines
which method is invoked
• Note that, if an invocation is in a loop, the exact
same line of code could execute different methods
at different times
• Polymorphic references are therefore resolved at
run-time, not during compilation
17
Polymorphism
• Note that, because all classes inherit from the
Object class, an Object reference can refer to
any type of object
• A Vector is designed to store Object
references
• The instanceOf operator can be used to
determine the class from which an object was
created
• See Variety.java
18
import java.awt.Point; import java.util.Vector;
class MyVariety {
public static void main (String[] args) {
Vector collector = new Vector();
Integer num1 = new Integer (10);collector.addElement (num1);
Point origin = new Point (0, 0); collector.addElement (origin);
Integer num2 = new Integer (37);collector.addElement (num2);
Point corner=new Point (12, 45);collector.addElement (corner);
int temp;
Object something;
for (int count=0; count < collector.size(); count++) {
something = collector.elementAt (count);
if (something instanceof Integer) {
temp = ((Integer)something).intValue() + 20;
System.out.println (something + " + 20 = " + temp); }
else
System.out.println ("Point: " + something);
}
} } // class Variety
Polymorphism
• See Firm2.java
StaffMember
Employee
Hourly
Volunteer
Executive
19
class Firm2 {
public static void main (String[] args) {
Staff personnel = new Staff();
personnel.payday();
} // method main
} // class Firm2
class Staff {
StaffMember[] staffList = new StaffMember[6];
public Staff() {
staffList[0] = new Executive ("Sam", "123 Main Line",
"555-0469", "123-45-6789", 1923.07);
staffList[1] = new Employee ("Carla", "456 Off Line",
"555-0101", "987-65-4321", 846.15);
staffList[2] = new Employee ("Woody", "789 Off Rocker",
"555-0000", "010-20-3040", 769.23);
staffList[3] = new Hourly ("Diane", "678 Fifth Ave.",
"555-0690", "958-47-3625", 8.55);
staffList[4] = new Volunteer ("Norm", "987 Suds Blvd.",
"555-8374");
staffList[5] = new Volunteer ("Cliff", "321 Duds Lane",
"555-7282");
((Executive)staffList[0]).awardBonus (5000);
((Hourly)staffList[3]).addHours (40);
} // constructor Staff
public void payday() {
double amount;
for (int count=0; count < staffList.length; count++) {
staffList[count].print();
amount = staffList[count].pay();
if (amount == 0.0)
System.out.println ("Thanks!");
else
System.out.println ("Paid: " + amount);
System.out.println ("**********************");
}
} // method payday
} // class Staff
class StaffMember {
protected String name;
protected String address;
protected String phoneNumber;
public StaffMember (String empName, String empAddress,
String empPhone) {
name = empName;
address = empAddress;
phoneNumber = empPhone;
} // constructor StaffMember
public double pay() {
return 0.0;
} // method pay
public void print() {
System.out.println ("Name: " + name);
System.out.println ("Address: " + address);
System.out.println ("Phone: " + phoneNumber);
} } // class StaffMember
class Volunteer extends StaffMember {
public Volunteer (String empName, String empAddress,
String empPhone) {
super (empName, empAddress, empPhone);
} // constructor Volunteer
public double pay() {
return 0.0;
} // method pay
} // class Volunteer
class Employee extends StaffMember {
protected String socialSecurityNumber;
protected double payRate;
public Employee (String empName, String empAddress,
String empPhone, String empSsnumber, double empRate) {
super (empName, empAddress, empPhone);
socialSecurityNumber = empSsnumber;
payRate = empRate;
} // constructor Employee
public double pay () {
return payRate;
} // method pay
public void print () {
super.print();
System.out.println ("SS number: " + socialSecurityNumber);
System.out.println ("Pay rate: " + payRate);
} // method print
} // class Employee
class Executive extends Employee {
private double bonus;
public Executive (String execName, String execAddress,
String execPhone, String execSsnumber,
double execRate) {
super (execName, execAddress, execPhone,
execSsnumber, execRate);
bonus = 0; // bonus yet to be awarded
} // constructor Executive
public void awardBonus (double execBonus) {
bonus = execBonus; } // method awardBonus
public double pay () {
double paycheck = super.pay() + bonus;
bonus = 0;
return paycheck; } // method pay
public void print () {
super.print();
System.out.println ("Current bonus: " + bonus);
} // method print
} // class Executive
class Hourly extends Employee {
private int hoursWorked;
public Hourly (String hrName, String hrAddress,
String hrPhone, String hrSsnumber, double hrRate) {
super (hrName, hrAddress, hrPhone, hrSsnumber, hrRate);
hoursWorked = 0;
} W public void addHours (int moreHours) {
hoursWorked += moreHours;
} // method addHours
public double pay () {
return payRate * hoursWorked;
} // method pay
public void print () {
super.print();
System.out.println ("Current hours: " + hoursWorked);
} // method print
} // class Hourly
Conclusion
• Inheritance: reuse the existing objects (is-a relation)
• Protect modifier: better encapsulation
• Use super to invoke parent’s methods.
• Overriding methods and overloaded methods
• All Java classes inherit from object class
• Polymorphism: which overriding method is invoked
based on the object’s type
• Widening & narrowing