790 likes | 806 Views
This article provides an introduction to inheritance in program design, explaining the syntax and implementation through examples. Topics discussed include overriding, OOP, polymorphism, and modifiers.
E N D
Inheritance - CIS 1068 Program Design and Abstraction Zhen Jiang CIS Dept. Temple University SERC 347, Main Campus Email: zhen.jiang@temple.edu
Table of Contents • Introduction to inheritance • Inheritance • Syntax • More! • Overridding • OOP (object-oriented programming) • Polymorphism • Modifiers • Abstract class and interfaces • GUI
Introduction • Write an Employee class with methods that return values for the following properties of employees at a particular company: • Work week: 40 hours • Annual salary: $40,000 • Paid time off: 2 weeks • Leave of absence form: Yellow form
// A class to represent employees public class Employee { public int getHours() { return 40; // works 40 hours / week } public double getSalary() { return 40000.0; // $40,000.00 / year } public int getVacationDays() { return 10; // 2 weeks' paid vacation } public String getVacationForm() { return "yellow"; // use the yellow form } }
Write a Secretary class with methods that return values for the following properties of secretaries at a particular company: Work week: 40 hours Annual salary: $40,000 Paid time off: 2 weeks Leave of absence form: Yellow form Add a method takeDictation that takes a string as a parameter and prints out the string prefixed by "Taking dictation of text: ".
// A class to represent secretaries public class Secretary { public int getHours() { return 40; // works 40 hours / week } public double getSalary() { return 40000.0; // $40,000.00 / year } public int getVacationDays() { return 10; // 2 weeks' paid vacation } public String getVacationForm() { return "yellow"; // use the yellow form } public void takeDictation(String text) { System.out.println("Taking dictation of text: " + text); } }
// A class to represent employees public class Employee { public int getHours() { return 40; } public double getSalary() { return 40000.0; } public int getVacationDays() { return 10; } public String getVacationForm() { return "yellow"; } } // A class to represent secretaries public class Secretary { public int getHours() { return 40; } public double getSalary() { return 40000.0; } public int getVacationDays() { return 10; } public String getVacationForm() { return "yellow"; } public void takeDictation(String text) { System.out.println("Taking dictation of text: " + text); } } Compare these two!
Inheritance: Is-a relationship is-a relationship: A hierarchical connection where one category can be treated as a specialized version of another. Examples: Every secretary is an employee. Every square is a rectangle. Every dog is a mammal.
code reuse: The practice of writing program code once and using it in many contexts. We'd like to be able to say the following: // A class to represent secretaries public class Secretary { <copy all the contents from Employee class> public void takeDictation(String text) { System.out.println("Taking dictation of text: " + text); } } That way we would be reusing the Employee code.
inheritance: A way to specify a relationship between two classes where one class inherits the state and behavior of another. The child class (also called subclass) inherits from the parent class (also called superclass). The subclass receives a copy of every field and method from the superclass.
Syntax Creating a subclass, general syntax: public class <subclass name> extends <superclass name> Example: public class Secretary extends Employee { .... } By extending Employee, each Secretary object automatically has a getHours, getSalary, getVacationDays, and getVacationForm method.
// A class to represent secretaries public class Secretary extends Employee { public void takeDictation(String text) { System.out.println("Taking dictation of text: " + text); } } • Improved Secretary class:
Writing even more classes Write a Marketer class that represents marketers who have the same properties as general employees, but instead of making only a paltry $40,000, marketers make $50,000! Can we still leverage the Employee class or do we have to re-write everything, because one method (getSalary) is different? If only Marketer could write a new version of the getSalary method, but inherit everything else…
Overriding methods override: To write a new version of a method in a subclass to replace the superclass's version. To override a superclass method, just write a new version of it in the subclass. This will replace the inherited version.
Marketer class // A class to represent marketers public class Marketer extends Employee { public void advertise() { System.out.println("Act now while supplies last!"); } public double getSalary() { return 50000.0; // $50,000.00 / year } }
OOP: Based in reality or too convenient? At many companies, all new employees attend a common orientation to learn general rules (e.g., what forms to fill out when). Each person receives a big manual of these rules. Each employee also attends a subdivision-specific orientation to learn rules specific to their subdivision (e.g., marketing department). Everyone receives a smaller manual of these rules.
The smaller manual adds some rules and also changes (read: overrides) some rules from the large manual (e.g., "use the pink form instead of the yellow form")
Why not just have a 22-page manual for lawyers, 21-page manual for secretaries, 23-page manual for marketers, etc…?
maintenance: If a common rule changes, only the common manual needs to be updated.
The 20 page manual manner is useful to be able to specify general rules that will apply to many groups. Locality A person can look at the manual for lawyers and quickly discover all rules that are specific to lawyers. It is also useful to specify a smaller set of rules for such a particular group, including being able to replace rules from the overall set (overriding, e.g., "use the pink form instead of the yellow form").
//base classpublic class PubA { public int x = 1; public void setX(){ x=2; } public int getX(){ return x; }} //attribute & method inheritancepublic class PubB extends PubA { public void setX(){x=3;}} overriding 2 3 PubA a = new PubA();PubB b = new PubB();a.setX();b.setX();System.out.println(a.getX());System.out.println(b.getX());
Why inheritance? • Need for Jbutton, FlowLayout, JTextField, etc • http://www.cis.temple.edu/~jiang/Extend_action.pdf • Need for a customized response from the computer for all GUI actions • http://www.cis.temple.edu/~jiang/MultiEventSource.pdf
public class Employee { private double salary; public Employee(double initialSalary) { salary = initialSalary; } public int getHours() { return 40; // 40 hours per week } public double getSalary() { return salary; } public int getVacationDays() { return 10; // 2 weeks' paid vacation } public String getVacationForm() { return "yellow"; // use the yellow form } }
Use the super() method to call the superclass’s constructor public class Marketer extends Employee { // inherits double salary public Marketer(double initialSalary) { //construct superclass super(initialSalary); } } - For every constructor of a subclass, the call to super() must be the first statement in the subclass’s constructor. - Make sure to give the same number of arguments as there are parameters in the definition of the superclass’s constructor.
Question: If a method is declared private, does a subclass inherit it? Actually, yes. Subclasses inherit everything that they don’t override. If a method is declared private, can a subclass call it? NO! Only code inside the same class can call a private method. What if you want a subclass to be able to use it? Use the protected access level
public class Employee { private double salary = 40000.00; public int getHours() { return 40; // works 40 hours / week } public double getSalary() { return salary; } public int getVacationDays() { return 10; // 2 weeks' paid vacation } public String getVacationForm() { return "yellow"; // use the yellow form } }
Subclasses cannot see salary directly! public class CEO extends Employee { public void giveMyselfRaise() { salary += 1000000.00; // Compile-time Error! } public static void main(String [] args) { CEO c = new CEO(); // This is fine, no error here // Access to salary field is indirect // We’re accessing the public getSalary() method System.out.println(“My salary is “ + c.getSalary()); } }
public class Employee { protected double salary = 40000.00; public int getHours() { return 40; // works 40 hours / week } public double getSalary() { return salary; } public int getVacationDays() { return 10; // 2 weeks' paid vacation } public String getVacationForm() { return "yellow"; // use the yellow form } }
Subclasses can see protected variables and methods just fine. public class CEO extends Employee { public void giveMyselfRaise() { salary += 1000000.00; // No longer an error } public static void main(String [] args) { CEO c = new CEO(); // This is fine, no error here // Access to salary field is indirect // We’re accessing the public getSalary() method System.out.println(“My salary is “ + c.getSalary()); } }
What would happen if .... public class Employee { private double salary = 40000.00; public int getHours() { return 40; // works 40 hours / week } public double getSalary() { return salary; } public void addToSalary(double raise) { salary += raise; } public int getVacationDays() { return 10; // 2 weeks' paid vacation } public String getVacationForm() { return "yellow"; // use the yellow form } }
public class CEO extends Employee { public void giveMyselfRaise() { addToSalary(1000000.00); } } CEO still has its own copy of the salary field, and this code will change the value of it appropriately. The fact that salary is private simply means that CEO can't access it directly. It can still call public (or protected) superclass methods that can access it.
//base class public class ProA { private int x = 1; protected void setX(int a){ x=a; } protected int getX(){ return x; }} //sub class public class ProB extends ProA { public int getB(){ setX(2); // your next step is to return x // but “return x” does not work // due to the private modifier, so return getX(); }} 1 2 ProA a = new ProA(); ProB b = new ProB(); System.out.println(a.getX()); System.out.println(b.getB());
A reference variable of type T can refer to an object of any subclass of T. Employee Laura = new Lawyer(); Employee Mark = new Marketer(); polymorphism: The ability for the same code to be used with several different types of objects and behave differently depending on the type of object used. Polymorphism
Employee Laura = new Lawyer(); System.out.println(Laura.getSalary()); // 40000.0 System.out.println(Laura.getVacationForm()); // "pink" You can call any method from Employee on the person variable, but not any method specific to Lawyer (such as sue). Once a method is called on that object, it behaves in its normal, overridden way (as a Lawyer, not as a normal Employee).
public class EmployeeMain { public static void main(String[] args) { Secretary laura = new Secretary(); Marketer mark = new Marketer(); printInfo(laura); printInfo(mark); } public static void printInfo(Employee empl) { System.out.println("salary = " + empl.getSalary()); System.out.println("days = " + empl.getVacationDays()); System.out.println("form = " + empl.getVacationForm()); System.out.println(); } } Output: salary = 40000.0 vacation days = 10 vacation form = yellow salary = 50000.0 vacation days = 10 vacation form = yellow public class Secretary extends Employee { public void takeDictation(String text) { System.out.println("Taking dictation of text: " + text); }} public class Marketer extends Employee { public void advertise() { System.out.println("Act now while supplies last!"); } public double getSalary() { return 50000.0; // $50,000.00 / year }} Polymorphism and parameters
public class EmployeeMain2 { public static void main(String[] args) { Employee[] employees = {new Secretary(), new Marketer() }; for (int i = 0; i < employees.length; i++) { System.out.println("salary = " + employees[i].getSalary()); System.out.println("vacation days = " + employees[i].getVacationDays()); System.out.println(); } } } Output: salary = 40000.0 vacation days = 10 salary = 50000.0 vacation days = 10 Polymorphism and arrays
Exercises public class Foo { public void method1() { System.out.println("foo 1"); } public void method2() { System.out.println("foo 2"); } public String toString() { return "foo"; } } public class Bar extends Foo { public void method2() { System.out.println("bar 2"); } } public class Baz extends Foo { public void method1() { System.out.println("baz 1"); } public String toString() { return "baz"; } } public class Mumble extends Baz { public void method2() { System.out.println("mumble 2"); } } • Assume that the following four classes have been declared:
What would be the output of the following client code? Foo[] pity = { new Baz(), new Bar(), new Mumble(), new Foo() }; for (int i = 0; i < pity.length; i++) { System.out.println(pity[i]); pity[i].method1(); pity[i].method2(); System.out.println(); }
The code produces the following output: baz baz 1 foo 2 foo foo 1 bar 2 baz baz 1 mumble 2 foo foo 1 foo 2
Variable Shadowing:Something to avoid!! • Polymorphism applies to methods in Java • But not to fields! public class A { int x = 1; int method() { return 1; } } public class B extends A { int x = 2; int method() { return 2; } } A a1 = new A(); A a2 = new B(); System.out.println(a1.method()); // prints 1 System.out.println(a2.method()); // prints 2 System.out.println(a1.x); // prints 1 System.out.println(a2.x); // prints 1 still! // Not like method, which prefers to its own.
Variable Shadowing: • When a class extends another class and defines a field with the same name, each object of the subclass contains two fields with that name. • The supclass’s version of the field is said to shadow the subclass’s version, making the subclass’s version invisible within that class. • This is called variable shadowing.
public class A { protected int x = 1; protected void setX(int a){ x=a;} protected int getX(){ return x;}} public class B extends A { protected int x = 3; public int getX(){ return x; } public int getB(){ return x;}} 1 3 3 1 3 A a = new A(); B b = new B();System.out.println(a.getX());System.out.println(b.getX());System.out.println(b.getB()); System.out.println(a.x);System.out.println(b.x); The difference is shadow! A a = new A(); A b = new B();System.out.println(a.getX());System.out.println(b.getX()); //System.out.println(b.getB()); System.out.println(a.x);System.out.println(b.x); 1 3 1 1
http://www.cis.temple.edu/~jiang/1068_modifier_inheritance.pdfhttp://www.cis.temple.edu/~jiang/1068_modifier_inheritance.pdf
Exercises • Slide 39 • PolymorphismDemo • www.cis.temple.edu/~jiang/PolymorphismDemo.pdf • www.cis.temple.edu/~jiang/Person.pdf • www.cis.temple.edu/~jiang/Student.pdf • www.cis.temple.edu/~jiang/Undergradaute.pdf
Modifiers • Public • A class, method, constructor, interface etc declared public can be accessed from any other class. Therefore fields, methods, blocks declared inside a public class can be accessed from any class belonging to the Java Universe. • Because of class inheritance, all public methods and variables of a class are inherited by its subclasses.
Private • Methods, Variables and Constructors that are declared private can only be accessed within the declared class itself. • Private access modifier is the most restrictive access level. Class and interfaces cannot be private. • Variables that are declared private can be accessed outside the class only if public accessor methods are present in the class.
Protected • Variables, methods and constructors which are declared protected in a superclass can be accessed only by the subclasses. • Protected access gives the subclass a chance to use the helper method or variable, while preventing a nonrelated class from trying to use it.