480 likes | 701 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 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: " + special.caloriesPerServing());
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
Business RetailBusiness ServiceBusiness 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) { 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
StaffMember 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 { 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