0% found this document useful (0 votes)
42 views

Module 8 Cosc 205 Inheritance N Poly

This module introduces the concept of inheritance in object-oriented programming. Inheritance allows a subclass to inherit attributes and behaviors from a superclass, allowing code reuse. A subclass can add its own fields and methods in addition to inheriting from the superclass. This creates a hierarchical class structure. The document provides an example inheritance hierarchy for members of a university community and includes code samples demonstrating inheritance between an Employee superclass and PartTimeEmployee subclass.
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
42 views

Module 8 Cosc 205 Inheritance N Poly

This module introduces the concept of inheritance in object-oriented programming. Inheritance allows a subclass to inherit attributes and behaviors from a superclass, allowing code reuse. A subclass can add its own fields and methods in addition to inheriting from the superclass. This creates a hierarchical class structure. The document provides an example inheritance hierarchy for members of a university community and includes code samples demonstrating inheritance between an Employee superclass and PartTimeEmployee subclass.
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 34

MODULE 8:

OBJECT ORIENTED
PROGRAMMING:
Inheritance
Adekola Olubukola, PhD, FNCS
Tel: +234803 374 6984
[email protected]
Module 8: Inheritance
GENERAL OBJECTIVE:
INHERITANCE
This introduces one of the primary capabilities of Object-Oriented
Programming Paradigm based on organizing classes into a hierarchical
structure described as the concept of Inheritance. It is a form of software
reuse in which a new class is created by absorbing (inheriting from) an
existing class’s members and embellishing them with new or modified
capabilities. This earns us time and quality advantages. The existing class is
called the superclass, and the new class is the subclass (also called derived or
child class). Each subclass can become a superclass for future subclasses. A
subclass can add its own fields and methods. Therefore, a subclass is more
specific than its superclass and represents a more specialized group of objects.
The subclass exhibits the behaviors of its superclass and can modify those
behaviors so that they operate appropriately for the subclass. The direct
superclass is the superclass from which the subclass explicitly inherits. An
indirect superclass is any class above the direct superclass in the class
hierarchy, which defines the inheritance relationships between classes.
INHERITANCE

In Java, the class hierarchy begins with class Object (in


package java.lang), which every class in Java directly or
indirectly extends (or “inherits from”). Methods in Object
are inherited by all other Java classes. Java supports only
single inheritance, in which each class is derived from
exactly one direct superclass. Unlike C++, Java does not
support multiple inheritance (which occurs when a class is
derived from more than one direct superclass).
Inheritance is described as “Is-a” relationship. In an is-a
relationship, an object of a subclass can also be treated as
an object of its superclass —e.g., a car is a vehicle.
Superclasses and Subclasses:
■ Superclasses tend to be “more general” and subclasses “more specific.”
For example, a CarLoan is a Loan. Thus, class CarLoan can be said to
inherit from class Loan. In this context, class Loan is a superclass and
class CarLoan is a subclass. A CarLoan is a specific type of Loan, but it’s
incorrect to claim that every Loan is a CarLoan—the Loan could be any
type of loan.
■ Because every subclass object is an object of its superclass, and one
superclass can have many subclasses, the set of objects represented by a
superclass is often larger than the set of objects represented by any of
its subclasses. For example, the superclass Vehicle represents all
vehicles, including cars, trucks, boats, bicycles and so on. By contrast,
subclass Car represents a smaller, more specific subset of vehicles.
Inheritance hierarchy for university Community Members:
■ A university community has thousands of members, including employees,
students and alumni. Employees are either faculty or staff members.
Faculty members are either administrators (e.g., deans and head of
departments) or teachers. The hierarchy could contain many other classes.
For example, students can be graduate or undergraduate students.
Undergraduate students can be freshmen, sophomores, juniors or seniors.
Each arrow in the hierarchy represents an is-a relationship. As we follow
the arrows upward in this class hierarchy, we can state, for instance, that
“an Employee is a Community-Member” and “a Teacher is a Faculty
member.” Community Member is the direct superclass of Employee,
Student and Alumnus is an indirect superclass of all the other classes in
the diagram. Starting from the bottom, you can follow the arrows and
apply the is-a relationship up to the topmost superclass. For example, an
Administrator is a Faculty member, is an Employee, is a
CommunityMember and, of course, is an Object (the root class).
Inheritance hierarchy for university Community Members:

CommunityMember

Employee Student Alumnus

Faculty Staff

Administrator Teacher

Inheritance relationships form treelike hierarchical structures


Inheritance
As mentioned earlier, Inheritance entails making a new class object
from an existing class either by customizing or adding new unique
characteristics. Therefore, stabilized components are easily reused.
E.g. an object of class “convertible” can be made from general
“automobile”.
A subclass can customize methods that it inherits from its
superclass. To do this, the subclass overrides (redefines) the
superclass method with an appropriate implementation (This is a
feature in OOP called Polymorphism- this type of polymorphism is
specifically called overriding).
Implementation example –Inheritance

■ One major advantage of object oriented approach to software


development is the privilege of re-using already written classes (either
by yourself or others). Take for example, if you have a need to write an
Employee class and there exist a pre-written class called Employee
that is purposed to do the similar task you are embarking on. Suppose
the existing class does not do all that you intended, for example if your
employees are part-time and you want attributes like hourlypay, or
methods like calculateWeeklyPay and setHourlyPay which do not
exist in the first class.
■ There won’t be any need to go and modify the old/existing class. All
you need do is to exploit the OOPL feature called Inheritance which
provides ability to extend existing classes by adding attributes and
methods to them.
Implementation example –Inheritance

■ Inheritance is the sharing of attributes and methods among


classes. We define a new class based on the existing/old one. The
new class inherits all the attributes and methods of the
old/existing, but also has attributes and methods of its own.
■ Using Employee class as an illustration, assuming the
first/existing Employee class has 2 attributes, number and name,
a user-defined constructor method, and get- and set- methods for
the attributes. Then, we define our new class called
PartTimeEmployee class; this will inherit the attributes and
methods of the Employee class but is also free to have attributes
and methods of its own e.g. attribute - hourlyPay, and method -
calculateweeklyPay.
Implementation example –Inheritance

■ The following figure shows an inheritance relationship between


Employee and PartTimeEmployee:

A UML notation for Inheritance


indicated with a triangle in the
diagram
// Implementation example of inheritance
1) //super class implementation
2) public class Employee {
3) private String number;
4) private String name;
5)
6) public Employee(String num, String nam)
7) {
8) number = num;
9) name = nam;
10) }
11)
12) public void setName(String nam)
13) {
14) name = nam;
15) }
16) public String getNumber()
17) {
18) return number;
19) }
20) public String getName()
21) {
22) return name;
23) }
24)
25) } // end of superclass
// Implementation example of inheritance
1) //subclass implemetation
2) public class EmployeePT extends Employee {
3) private double hourlyPay;
4) public EmployeePT (String num, String nam, double hrPay)
5) {
6) super(num, nam);
7) hourlyPay = hrPay;
8) }
9) public double getHourlyPay()
10) {
11) return hourlyPay;
12) }
13) public void setHourlyPay(double hrPay)
14) {
15) hourlyPay = hrPay;
16) }
17) public double calcWeeklyPay(int noOfhr)
18) {
19) return noOfhr * hourlyPay;
20) }
21) } //end of subclass
// Implementation example of inheritance
1) //client / main program implemetation
2) import java.util.Scanner;
3) public class EmployeePTTest {
4) public static void main(String[] args)
5) {
6) Scanner keyIn = new Scanner(System.in);
7) Scanner keyStr = new Scanner(System.in);
8) String number, name;
9) double pay;
10) double hours;
11) EmployeePT emp;
12)
13) // read in values
14) System.out.println("Emp no");
15) number = keyStr.nextLine();
22) emp = new EmployeePT(number, name, pay);
16) System.out.println("Name");
23) System.out.println(emp.getName());
17) name = keyStr.nextLine();
24) System.out.println(emp.getNumber());
18) System.out.println("Pay");
25) System.out.println(emp.calcWeeklyPay(hours));
19) pay = keyIn.nextDouble();
20) System.out.println("Hr worked");
26) }
21) hours = keyIn.nextDouble();
27) }
Writing Classes– Good Design Hints
■ Always keep data private – a programmer may need to write an accessor or mutator method occasionally, but are
still better off keeping the instance fields private. When data are kept private, changes in their representation do
not affect the user of the class, and bugs are easier to detect. Doing anything else violates encapsulation.
■ Always initialize data – Java will not initialize local variables, it will initialize instance of objects. Initialize the
variables explicitly, either by supplying a default or by setting defaults in all constructors
■ Don’t use too many basic types in a class – The idea is to replace multiple related uses of basic types with other
classes
■ Not all fields need individual field accessors and mutators – a programmer may need to do a set or get, objects
have instance variables that programmers may not want others to set or get.
■ Use a standard form for class definitions – the users of the class are more interested in the public interface than
in the details of the private implementation; and they are more interested in the methods than in data
■ Break up classes with too many responsibilities – avoid the extremes (one complicated class (called God class)
or one simple class with just one method).
■ Make the names of your classes and methods reflect their responsibilities – just as variables should have
meaningful name that reflect what they represent, so should classes. A good convention is that a class should be a
noun or a noun preceded by an adjective or a gerund (an “ing”) and methods standard convention is begin with a
lowercase followed by an uppercase name.
More on Classes and Inheritance
Key Points:
■ A class’s private members are accessible only within the class itself.
■ A superclass’s protected members can be accessed by members of that
superclass, by members of its subclasses and by members of other classes in
the same package—protected members also have package access.
■ public members of the superclass become public members of the subclass,
and protected members of the superclass become protected members of the
subclass.
■ When a subclass method overrides an inherited superclass method, the
superclass method can be accessed from the subclass by preceding the
superclass method name with keyword super and a dot (.) separator.
Implementation Example:
■ BasePlusCommissionEmployee is-a CommissionEmployee, where firstName,
lastName, socialSecurityNumber, grossSales and commissionRate are attributes
to be inherited, while baseSalary is the only attribute specific to
BasePlusCommissionEmployee subclass.
a) If you have to restrict the security and the integrity of these inherited attributes
to its super class and still make them accessible for the subclass, state what to
do.
b) Show implementation of CommissionEmployee existing already as a
superclass, implement the subclass BasePlusCommissionEmployee depicting
inheritance relationship clearly defining baseSalary attribute and the class’s
constructor method.
c) Implement an override of the method called earnings which simply adds
baseSalary to the super class earnings method implementation.
Note: earnings method returns the product of commissionRate and grossSales in
the super class.
Implementation Example: Solution
a) To promote data security and integrity, define the attributes to be inherited as private
then create public methods to access them (getter and setter methods).
b) The following implements the CommissionEmployee as a superclass:

1) //CommissionEmployee extends (i.e., inherits from) class Object (from


//package java.lang). Meanwhile, including this root base class is optional.
2) public class CommissionEmployee extends Object
3) {
4) private String firstName;
5) private String lastName;
6) private String socialSecurityNumber;
7) private double grossSales; // gross weekly sales
8) private double commissionRate; // commission percentage
CommissionEmployee Implementation Contd..
9) // five-argument constructor
10) public CommissionEmployee( String first, String last, String
ssn, 25) // return first name
11) double sales, double rate ) 26) public String getFirstName()
12) { 27) {
13) // implicit call to Object constructor occurs here 28) return firstName;
29) } // end method getFirstName
14) firstName = first;
15) lastName = last; 30) // set last name
16) socialSecurityNumber = ssn; 31) public void setLastName( String
17) setGrossSales( sales ); // validate and store gross sales last )
18) setCommissionRate( rate ); // validate and store commission 32) {
rate 33) lastName = last; // should validate
19) } // end five-argument CommissionEmployee constructor 34) } // end method setLastName
20) // set first name
21) public void setFirstName( String first ) 35) // return last name
36) public String getLastName()
22) {
37) {
23) firstName = first; // should validate 38) return lastName;
24) } // end method setFirstName 39) } // end method getLastName
CommissionEmployee Implementation Contd..
40) // set social security number 59) // return gross sales amount
41) public void setSocialSecurityNumber( String ssn ) 60) public double getGrossSales()
42) { 61) {
43) socialSecurityNumber = ssn; // should validate 62) return grossSales;
44) } // end method setSocialSecurityNumber 63) } // end method getGrossSales
45) // return social security number 64) // set commission rate
65) public void setCommissionRate( double rate )
46) public String getSocialSecurityNumber()
66) {
47) { 67) if ( rate > 0.0 && rate < 1.0 )
48) return socialSecurityNumber; 68) commissionRate = rate;
49) } // end method getSocialSecurityNumber 69) else
50) // set gross sales amount 70) throw new IllegalArgumentException(
51) public void setGrossSales( double sales ) 71) "Commission rate must be > 0.0 and < 1.0" );
52) { 72) } // end method setCommissionRate
53) if ( sales >= 0.0 )
54) grossSales = sales; 73) // return commission rate
74) public double getCommissionRate()
55) else
75) {
56) throw new IllegalArgumentException( 76) return commissionRate;
57) "Gross sales must be >= 0.0" ); 77) } // end method getCommissionRate
58) } // end method setGrossSales
CommissionEmployee Implementation Contd..
78) // calculate earnings
79) public double earnings()
80) {
81) return commissionRate * grossSales;
82) } // end method earnings

83) // return String representation of CommissionEmployee object


84) @Override // indicates that this method overrides a superclass method
85) public String toString()
86) {
87) return String.format( "%s: %s %s\n%s: %s\n%s: %.2f\n%s: %.2f",
88) "commission employee", firstName, lastName,
89) "social security number", socialSecurityNumber,
90) "gross sales", grossSales,
91) "commission rate", commissionRate );
92) } // end method toString
93) } // end class CommissionEmployee
■ Constructors are not inherited However, a superclass’s constructors are
still available to subclasses. In fact, the first task of any subclass
constructor is to call its direct superclass’s constructor, either explicitly
or implicitly (if no constructor call is specified), to ensure that the
instance variables inherited from the superclass are initialized properly.
■ The @Override annotation indicates that method toString should
override a superclass method.
■ common errors include naming the subclass method incorrectly, or using
the wrong number or types of parameters in the parameter list. Each of
these problems creates an unintentional overload of the superclass
method.
■ It’s a syntax error to override a method with a more restricted access
modifier—a public method of the superclass cannot become a protected
or private method in the subclass; a protected method of the superclass
cannot become a private method in the subclass.
//CommissionEmployee as Super Class
■ public class CommissionEmployee extends Object
■ {
■ private String firstName;
■ private String lastName;
■ private String socialSecurityNumber;
■ private double grossSales; // gross weekly sales
■ private double commissionRate;
■ // constructors go here
■ // calculate earnings
■ public double earnings()
■ {
■ return commissionRate * grossSales;
■ }
// sub class creation using “extends”
■ public class BasePlusCommissionEmployee extends CommissionEmployee
■ {
■ private double baseSalary; // base salary per week
■  
■ // six-argument constructor
■ public BasePlusCommissionEmployee( String first, String last, String ssn,
double sales, double rate, double salary )
■ {
■ // explicit call to superclass CommissionEmployee constructor
■ super( first, last, ssn, sales, rate );
■ setBaseSalary( salary ); // validate and store base salary
■ }//end of constructor
■ // set base salary
■ public void setBaseSalary( double salary )
■ {
■ if ( salary >= 0.0 )
■ baseSalary = salary;
■ else
■ throw new IllegalArgumentException(
■ "Base salary must be >= 0.0" );
■ } // end method setBaseSalary

■ // return base salary


■ public double getBaseSalary()
■ {
■ return baseSalary;
■ } // end method getBaseSalary
■ @Override // indicates that this method overrides a superclass method
■ public double earnings()
■ {
■ // not allowed: commissionRate and grossSales private in superclass
■ return baseSalary + ( commissionRate * grossSales );
■ }
■ // return String representation of BasePlusCommissionEmployee
@Override // indicates that this method overrides a superclass method
■ public String toString()
■ {
■ // not allowed: attempts to access private superclass members
■ return String.format(
■ "%s: %s %s\n%s: %s\n%s: %.2f\n%s: %.2f\n%s: %.2f",
■ "base-salaried commission employee", firstName, lastName,
■ "social security number", socialSecurityNumber,
■ "gross sales", grossSales, "commission rate", commissionRate,
■ "base salary", baseSalary );
■ } // end method toString
■ } // end class BasePlusCommissionEmployee
■ A way out is to declare superclass instance variables as
protected so that subclasses could access them. Inheriting
protected instance variables slightly increases performance,
because we can directly access the variables in the subclass
without incurring the overhead of a set or get method call. But
a subclass object can assign an invalid value to the variable,
possibly leaving the object in an inconsistent state.
■ Another problem with using protected instance variables is that
subclass methods are more likely to be written so that they
depend on the superclass’s data implementation. In practice,
subclasses should depend only on the superclass services (i.e.,
non-private methods) and not on the superclass data
implementation.
■ With protected instance variables in the superclass, we may need to
modify all the subclasses of the superclass if the superclass
implementation changes. For example, if for some reason we were to
change the names of instance variables firstName and lastName to first
and last, then we would have to do so for all occurrences in which a
subclass directly references superclass instance variables firstName and
lastName. In such a case, the software is said to be fragile or brittle,
because a small change in the superclass can “break” subclass
implementation. You should be able to change the superclass
implementation while still providing the same services to the subclasses.
■ A third problem is that a class’s protected members are visible to all
classes in the same package as the class containing the protected
members—this is not always desirable.
■ In most cases, however, it’s better to use private instance variables, build
public set/get methods to assess them -this is to encourage proper
software engineering, and leave code optimization issues to the compiler.
Your code will be easier to maintain, modify and debug.
■ // update on super class
■ public class CommissionEmployee
■ {
■ private String firstName;
■ private String lastName;
■ private String socialSecurityNumber;
■ private double grossSales; // gross weekly sales
■ private double commissionRate;
■ // write get methods for the instance variables
■ public double getCommissionRate()
■ {
■ return commissionRate;
■ }
■ public double getGrossSales()
■ {
■ return grossSales;
■ }
■ public double earnings()
■ {
■ return getCommissionRate()* getGrossSales();
■ }
■ @Override // indicates that this method overrides a superclass method
■ public String toString()
■ {
■ return String.format( "%s: %s %s\n%s: %s\n%s: %.2f\n%s: %.2f",
■ "commission employee", , , getFirstName() getLastName()
■ "social security number", , getSocialSecurityNumber()
■ "gross sales", , getGrossSales()
■ "commission rate",getCommissionRate() );
■ } // end method toString
■ } // end class

■ // Modification on the subclass


■ public class BasePlusCommissionEmployee extends CommissionEmployee
■ {
■ @Override // indicates that this method overrides a superclass method
■ public double earnings()
■ {
■ return getBaseSalary() + super.earnings();
■ } //
■ // return String representation of BasePlusCommissionEmployee
■ @Override // indicates that this method overrides a superclass method
■ public String toString()
■ {
■ return String.format( "%s %s\n%s: %.2f", "base-salaried",
■ super.toString(), "base salary", getBaseSalary() );
■ } // end method toString
} // end class BasePlusCommissionEmployee
■ Note the syntax used to invoke an overridden superclass method
from a subclass—place the keyword super and a dot (.)
separator before the superclass method name. This method
invocation is a good software engineering practice—if a method
performs all or some of the actions needed by another method,
call that method rather than duplicate its code. If we did not use
“super.” then BasePlusCommissionEmployee’s earnings
method would call itself rather than the superclass version. This
would result in a phenomenon called infinite recursion, which
would eventually cause the method-call stack to overflow—a
fatal runtime error.
■ When a program creates a BasePlusCommissionEmployee
object, its constructor is called. That constructor calls
CommissionEmployee’s constructor which in turn calls
Object’s constructor. Class Object’s constructor has an empty
body, so it immediately returns control to
CommissionEmployee’s constructor, which then initializes the
CommissionEmployee private instance variables that are part
of the Base- PlusCommissionEmployee object. When
CommissionEmployee’s constructor completes execution, it
returns control to BasePlusCommissionEmployee’s
constructor, which initializes the
BasePlusCommissionEmployee object’s baseSalary.
Software Engineering with Inheritance
When you extend a class, the new class inherits the superclass’s members—though
the private superclass members are hidden in the new class. You can customize the
new class to meet your needs by including additional members and by overriding
superclass members. Doing this does not require the subclass programmer to
change (or even have access to) the superclass’s source code. Java simply requires
access to the superclass’s .class file so it can compile and execute any program that
uses or extends the superclass. This powerful capability is attractive to independent
software vendors (ISVs), who can develop proprietary classes for sale or license
and make them available to users in bytecode format. Users then can derive new
classes from these library classes rapidly and without accessing the ISVs’
proprietary source code.
People experienced with such projects say that effective software reuse improves
the software-development process and Object-oriented programming facilitates
software reuse.

You might also like