1 lecture 8 inheritance instructors: fu-chiung cheng ( 鄭福炯 ) associate professor computer...
TRANSCRIPT
1
Lecture 8Inheritance
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
2
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
3
Inheritance
• Inheritance relationships: – base class: Vehicle– derived class: Car– Car inherits data & methods
from Vehicle• Inheritance creates an is-a relationship, meaning
the child is-a more specific version of the parent
Vehicle
Car
4
Deriving Subclasses
• The reserved word extends is used to establish an inheritance relationship
class Car extends Vehicle {
// class contents
}
• See Words.java
class Book { protected int pages = 1500; public void page_message () { System.out.println ("Number of pages: " + pages); } // method page_message} // class Bookclass Dictionary extends Book { private int definitions = 52500; public void definition_message () { System.out.println ("Number of definitions: "+definitions); System.out.println ("Definitions per page: "+definitions/pages); } // method definition_message} // class Dictionaryclass Words { // Test Driver public static void main (String[] args) { Dictionary webster = new Dictionary (); webster.page_message(); webster.definition_message(); } } // class Words
5
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
6
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
class Book { protected int pages; public Book (int num_pages) { pages = num_pages; } public void page_message () { System.out.println ("Number of pages: " + pages); } } // class Bookclass Dictionary extends Book { private int definitions; public Dictionary (int num_pages, int num_definitions) { super (num_pages); definitions = num_definitions; } // constructor Dictionary public void definition_message () { System.out.println ("Number of definitions: " + definitions); System.out.println ("Definitions per page: "+definitions/pages); } // method definition_message} // class Dictionary
class Words2 { public static void main (String[] args) { Dictionary webster = new Dictionary (1500, 52500); webster.page_message(); webster.definition_message(); System.out.println(webster); // try printly object } // method main} // class Words2
7
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
class Food { final private int CALORIES_PER_GRAM = 9; private int fat; protected int servings; public Food (int num_fat_grams, int num_servings) { fat = num_fat_grams; servings = num_servings; } // constructor Food private int calories() { return fat * CALORIES_PER_GRAM; } public int calories_per_serving() { return (calories() / servings); } } // class Foodclass Pizza extends Food { public Pizza (int amount_fat) { super (amount_fat, 8); } } // class Pizza// main test driver Pizza special = new Pizza (275); System.out.println ("Calories per serving: " + special.calories_per_serving());
class Food { final private int CALORIES_PER_GRAM = 9; private int fat; protected int servings; public Food (int num_fat_grams, int num_servings) { fat = num_fat_grams; servings = num_servings; } // constructor Food private int calories() { return fat * CALORIES_PER_GRAM; } public int calories_per_serving() { return (calories() / servings); } } // class Foodclass Pizza extends Food { public Pizza (int amount_fat) { super (amount_fat, 8); } } // class Pizza// main test driver Pizza special = new Pizza (275); System.out.println ("Calories per serving: " + special.calories_per_serving());
class Student { protected String name; protected int num_courses; public Student (String student_name, int classes) { name = student_name; num_courses = classes; } // constructor Student public void info () { System.out.println ("Student name: " + name); System.out.println ("Number of courses: " +
num_courses); } // method info public static void main(String[] argv) {
System.out.println("Student Main"); }} // class Student
class Grad_Student extends Student { private String source; private double rate; public Grad_Student (String student_name, int classes, String support_source, double hourly_rate) { super (student_name, classes); source = support_source; rate = hourly_rate; } // constructor Grad_Student public void support () { System.out.println ("Support source: " + source); System.out.println ("Hourly pay rate: " + rate); } // method support} // class Grad_Student
class School { public static void main (String[] args) { Student sammy = new Student ("Sammy", 5); Grad_Student pete = new Grad_Student ("Pete", 3, "Teaching Assistant", 8.75); sammy.info(); System.out.println(); pete.info(); pete.support(); } // method main} // class School
8
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
class MyMessages { public static void main (String[] args) { Thought parked = new Thought(); Advice dates = new Advice(); parked.message(); dates.message(); } } // class Messagesclass Thought { public void message() { System.out.println (”Message"); } } // class Thoughtclass Advice extends Thought { public void message() { // overriding method System.out.println (”Advice."); } // method message} // class Advice
9
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
10
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
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.award_bonus (2000); System.out.println ("Paid: " + sam.pay()); System.out.println(); } } // class Firm
class Employee { protected String name; protected String address; protected String phone_number; protected String social_security_number; protected double pay_rate; public Employee (String emp_name, String emp_address, String emp_phone,String emp_ssnumber, double emp_rate) { name = emp_name; address = emp_address; phone_number = emp_phone; pay_rate = emp_rate; social_security_number = emp_ssnumber; } // constructor Employee public double pay () { return pay_rate; } // method pay public void print () { System.out.println (name + " " + social_security_number); System.out.println (address); System.out.println (phone_number); } } // class Employee
class Executive extends Employee { private double bonus; public Executive (String exec_name, String exec_address, String exec_phone, String exec_ssnumber, double exec_rate) { super (exec_name, exec_address, exec_phone,
exec_ssnumber, exec_rate); // call parent’s constructor bonus = 0; // bonus yet to be awarded } // constructor Executive public void award_bonus (double exec_bonus) { bonus = exec_bonus; } // method award_bonus public double pay () { double paycheck = super.pay() + bonus; // call parent’s method bonus = 0; return paycheck; } // method pay} // class Executive
11
Class Hierarchies
• A child class of one parent can be the parent of another child, forming class hierarchies:
Business
Service_BusinessRetail_Business
K-MartMacy's Kinko's
12
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
class Accounts2 { public static void main (String[] args) { Savings_Account savings = new Savings_Account (4321, 5028.45, 0.02); Bonus_Saver_Account big_savings = new Bonus_Saver_Account (6543, 1475.85, 0.02); Checking_Account checking = new Checking_Account (9876, 269.93, savings); savings.deposit (148.04); big_savings.deposit (41.52); savings.withdrawal (725.55); big_savings.withdrawal (120.38); checking.withdrawal (320.18); } // method main} // class Accounts2
class Bank_Account { protected int account; protected double balance; public Bank_Account (int account_num, double initial_balance) { account = account_num; balance = initial_balance; } 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 Bank_Account
class Checking_Account extends Bank_Account { private Savings_Account overdraft; public Checking_Account (int account_num,
double initial_balance, Savings_Account protection) { super (account_num, initial_balance); overdraft = protection; } // constructor Checking_Account 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 Checking_Account
class Savings_Account extends Bank_Account { protected double rate; public Savings_Account (int account_num, double initial_balance, double interest_rate) { super (account_num, initial_balance); rate = interest_rate; } // constructor Savings_Account public void add_interest () { balance += balance * rate; System.out.println ("Interest added to account: " + account); System.out.println ("New balance: " + balance); System.out.println(); } // method add_interest} // class Savings_Account
class Bonus_Saver_Account extends Savings_Account { private final int PENALTY = 25; private final double BONUS_RATE = 0.03; public Bonus_Saver_Account (int account_num, double initial_balance, double interest_rate) { super (account_num, initial_balance, interest_rate); } // constructor Super_Saver_Account public boolean withdrawal (double amount) { System.out.println ("Penalty incurred: " + PENALTY); return super.withdrawal (amount+PENALTY); } // method withdrawal public void add_interest () { balance += balance * (rate + BONUS_RATE); System.out.println ("Interest added to account: " + account); System.out.println ("New balance: " + balance); System.out.println(); } // method add_interest
13
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 Test_toString.java
import java.awt.Point;class Test_toString { public static void main (String[] args) { Integer num = new Integer (25); Point origin = new Point (0, 0); Any_Class my_class = new Any_Class(); String num_string = num.toString(); String point_string = origin.toString(); String class_string = my_class.toString(); System.out.println (num_string); System.out.println (point_string); System.out.println (class_string); } // method main} // class Test_toStringclass Any_Class { public String toString() { return "I am Any_Class"; } // method toString} // class Any_Class
14
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();
15
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
16
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
17
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
18
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
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
class Firm2 { public static void main (String[] args) { Staff personnel = new Staff(); personnel.payday(); } // method main} // class Firm2
class Staff { Staff_Member[] staff_list = new Staff_Member[6]; public Staff() { staff_list[0] = new Executive ("Sam", "123 Main Line", "555-0469", "123-45-6789", 1923.07); staff_list[1] = new Employee ("Carla", "456 Off Line", "555-0101", "987-65-4321", 846.15); staff_list[2] = new Employee ("Woody", "789 Off Rocker", "555-0000", "010-20-3040", 769.23); staff_list[3] = new Hourly ("Diane", "678 Fifth Ave.", "555-0690", "958-47-3625", 8.55); staff_list[4] = new Volunteer ("Norm", "987 Suds Blvd.", "555-8374"); staff_list[5] = new Volunteer ("Cliff", "321 Duds Lane", "555-7282"); ((Executive)staff_list[0]).award_bonus (5000); ((Hourly)staff_list[3]).add_hours (40); } // constructor Staff
public void payday() { double amount; for (int count=0; count < staff_list.length; count++) { staff_list[count].print(); amount = staff_list[count].pay(); if (amount == 0.0) System.out.println ("Thanks!"); else System.out.println ("Paid: " + amount); System.out.println ("**********************"); }
} // method payday
} // class Staff
class Staff_Member { protected String name; protected String address; protected String phone_number; public Staff_Member (String emp_name, String emp_address, String emp_phone) { name = emp_name; address = emp_address; phone_number = emp_phone; } // constructor Staff_Member 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: " + phone_number); } } // class Staff_Member
class Volunteer extends Staff_Member {
public Volunteer (String emp_name, String emp_address, String emp_phone) {
super (emp_name, emp_address, emp_phone);
} // constructor Volunteer
public double pay() { return 0.0; } // method pay
} // class Volunteer
class Employee extends Staff_Member { protected String social_security_number; protected double pay_rate; public Employee (String emp_name, String emp_address, String emp_phone, String emp_ssnumber, double emp_rate) { super (emp_name, emp_address, emp_phone); social_security_number = emp_ssnumber; pay_rate = emp_rate; } // constructor Employee public double pay () { return pay_rate; } // method pay public void print () { super.print(); System.out.println ("SS number: " + social_security_number); System.out.println ("Pay rate: " + pay_rate); } // method print} // class Employee
class Executive extends Employee { private double bonus; public Executive (String exec_name, String exec_address, String exec_phone, String exec_ssnumber, double exec_rate) { super (exec_name, exec_address, exec_phone,
exec_ssnumber, exec_rate); bonus = 0; // bonus yet to be awarded } // constructor Executive public void award_bonus (double exec_bonus) { bonus = exec_bonus; } // method award_bonus 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 hours_worked; public Hourly (String hr_name, String hr_address, String hr_phone, String hr_ssnumber, double hr_rate) { super (hr_name, hr_address, hr_phone, hr_ssnumber, hr_rate); hours_worked = 0; } // constructor Hourly public void add_hours (int more_hours) { hours_worked += more_hours; } // method add_hours public double pay () { return pay_rate * hours_worked; } // method pay public void print () { super.print(); System.out.println ("Current hours: " + hours_worked); } // 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