480 likes | 561 Views
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.
E N D
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 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
Vehicle Car 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 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 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 Dictionary class Words { // Test Driver public static void main (String[] args) { Dictionary webster = new Dictionary (); webster.page_message(); webster.definition_message(); } } // 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 num_pages) { pages = num_pages; } public void page_message () { System.out.println ("Number of pages: " + pages); } } // class Book class 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
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 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 Food class 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 Food class 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
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.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
Business Retail_Business Service_Business Macy's K-Mart Kinko's Class Hierarchies • A child class of one parent can be the parent of another child, forming class hierarchies: 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) { 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
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 13
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_toString class Any_Class { public String toString() { return "I am Any_Class"; } // method toString } // class Any_Class
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
Staff_Member Employee Volunteer Hourly Executive Polymorphism • See Firm2.java 19
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