Inheritance and Polymorphism
CHAPTER 9
Relationships Between Classes
The most common types of relationships:
Dependency
Aggregation
Inheritance
Understanding Dependency in Java
A class dependency occurs when one class relies on another class to
perform its operations.
Managing dependencies is necessary for maintaining clean, modular, and
easily testable code
Dependency
class Timer { This is a dependency because:
void start() { Game does not store Timer.
[Link]("Timer started");
} It's only used inside the method.
} The object is passed temporarily.
class Game {
void play(Timer timer) { // dependency
[Link](); Game
}
}
Timer
Dependency
• It is a good practice to minimize the coupling (i.e., dependency) between
classes.
• When a class changes, coupled classes may also need updating.
Aggregation: has-a Relationship
A class aggregates another if its objects contain references to other
types of objects.
Example: a Quiz class aggregates a Question class.
The UML for aggregation:
Aggregation
A class may use Scanners without ever declaring an instance
variable of type Scanner. This is dependency NOT aggregation
Aggregation is a stronger form of dependency.
Aggregation uses instance variable to remember another object
between method calls.
public class Quiz
{
. . .
private ArrayList<Question> questions;
. . .
}
Aggregation
• A car has a motor and tires.
• In object-oriented design, this “has-a” relationship is called
aggregation.
What is Inheritance
A primary feature of object-oriented programming.
A form of software reuse in which a new class is created by absorbing
an existing class’s members and enhancing them with new or modified
functionality.
Allows programmers to specify that the new class should inherit the
members of an existing class rather than declare completely new
members (data/behaviors).
Class Relationships and Inheritance
Scanners are used in the Car class to input Car data (Dependency)
Every car has a tire (or four). (Aggregation)
Every car is a vehicle. (Inheritance)
class Car extends Vehicle{
private Tire[] tires;
. . .
}
Figure 6 UML Notation for
Inheritance and Aggregation
UML Relationship Symbols
Relationship Symbol Line Style Arrow Tip
Inheritance Solid Triangle
Interface Implementation Dotted Triangle
Aggregation Solid Diamond
Dependency Dotted Open
Multiplicities
any number (zero or more): *
one or more: 1..*
zero or one: 0..1
exactly one: 1
Inheritance Hierarchy
superclass
subclass
Inheritance: Terminology
Inheritance is a relationship between a generalized superclass and a specialized
subclass.
Subclass: more specific/specialized. Inherit the methods and data fields from the
superclass, and define their own, creating more specialized objects.
Superclass: more general.
One superclass can have many subclasses, and the set of objects represented by
a superclass is larger than the set of objects represented by any of its subclasses.
Inheritance: Terminology
Direct superclass:
◦Superclass from which a subclass explicitly inherits.
◦Example: direct superclass of the class Faculty is Employee.
Indirect superclass:
◦Any class above the direct superclass in the class hierarchy.
◦Example: indirect superclass of Teacher is Employee.
Class Hierarchy
Class hierarchy defines the inheritance relationship between
classes.
In single inheritance, a class is derived from one direct superclass.
In Java, multiple inheritance is not supported; a class can only have
one direct superclass.
Substitution Principle: is-a relationship
A member of a subclass is also a member of any direct or indirect superclass.
An Employee is-a CommunityMember, Admin is-a Faculty.
You can substitute a Faculty object in any algorithm that expects an Employee (Faculty
is-a Employee).
The reverse is not true (Employee is-a Faculty) -> we cannot assume that every
Employee has the data and behaviors of Faculty.
Examples:
SuperClass SubClass
Student GradStudent, UnderGradStudent
Shape Circle, Triangle, Rectangle
Loan CarLoan, HomeLoan, BusinessLoan
Employee Part-Time, Full-Time, Temporary
When to use Inheritance
Inheritance may be useful when:
o New class that has the attributes of an existing class but defines additional
data/methods.
o New class has the same behaviors as an existing class, but they are implemented in a
different way.
Use a single class for variation in values, inheritance for variation in behavior.
Example:
▪ Two vehicles vary by fuel efficiency – use an instance variable to describe the
variation.
▪ Two vehicles behave differently – use inheritance.
Specialization vs. Generalization
One object class (the specialization) is a subset of another (the generalization).
In specialization you:
◦ Begin by defining all common behaviors of a group of objects. I.e., all person objects
share a first name and a last name.
◦ Narrow the focus to describe groups of objects that have all the attributes and
behaviors of the superclass objects, but with additional attributes or modified
behaviors.
Specialization vs. Generalization
One object class (the specialization) is a subset of another (the generalization).
In generalization, you can do the opposite.
◦ Start with a number of subclasses, then identify all common properties and
behaviors.
◦ Common features can be generalized (moved) to a superclass.
◦ Common attributes and behaviors only must be defined once.
Self Check 9.1
Consider classes Manager and Employee. Which should be the
superclass, and which should be the subclass?
Answer: Because every manager is an employee but not the
other way around, the Manager class is more specialized. It is
the subclass, and Employee is the superclass.
Self Check 9.2
What are the inheritance relationships between classes
BankAccount, CheckingAccount, and SavingsAccount?
Answer: CheckingAccount and SavingsAccount both
inherit from the more general class BankAccount.
Self Check 9.3
Should a class Quiz inherit from the class Question? Why or
why not?
Answer: It shouldn’t. A quiz isn’t a question; it has questions.
Example: Product/Food/Clothing
Person
is-a is-a
Student Teacher
Creating Subclasses - extends
To indicate that one class is a subclass of another, use the extends keyword.
Usage: public class Dog extends Animal {…}
Visibility and Inheritance - protected
What is inherited?
◦ Public and protected instance members (methods and data).
◦ Constructors and private members are not inherited!
◦ Static methods are not inherited!
The protected modifier indicates that a super classes protected members can be
accessed by members of its subclasses and by members of classes in the same package.
Subclass can invoke any methods from its own class or its superclass.
Constructors and Inheritance
Constructor methods are not inherited.
Constructors of the superclass are always called, either
explicitly (the constructor is called from the constructor code) or
implicitly (automatically by Java if no call is specified in the code).
If the code does not have an explicit call to the superclass
constructor, Java implicitly calls the superclass’s default constructor.
Creating an Object - Constructors
Instantiating a subclass begins a chain of constructor calls.
1. Subclass constructor first calls direct superclass constructor either explicitly (using
the keyword super) or implicitly
2. If the superclass is derived from another class, superclass constructor calls its
superclass constructor.
3. The last constructor called is always the constructor for the Object class, since
it is at the top of the hierarchy.
4. The original class constructor’s body finishes executing last.
Each superclass’s constructor manipulates the instance variables that will be
inherited by the subclass.
super Keyword
super is used to refer to the direct superclass of a class.
Can be used to explicitly invoke the superclass methods and constructors.
To explicitly invoke a superclass constructor, super( args ) is used.
Invokes the superclass constructor, passing it the values to be initialized. The
superclass constructor then initialized the values of the inherited data fields for the
current object.
The prefix super can also be used to call a method of the superclass.
For example, [Link]()
Creating Subclass Objects
Imagine we have the following inheritance hierarchy:
What will be output when the following statement is executed:
C obj = new C();
Invoking Methods on Objects
When a method is invoked:
Java first searches the class of the current object for a matching method.
If none exists, it searches the inherited methods of the direct superclass, and so on,
until it finds a matching method.
It will search all superclass methods, up to the root Object class.
If a matching method is not found, a method not found error will be reported.
Method Overriding
Method in subclass with same signature as superclass method.
When subclass inherits the method from the super class, as well as defines its
own method -> method overrides the super class method.
For example, in class Person there is an introduce() method that is
inherited by Student and Teacher.
Students and Teachers introduce themselves in different ways.
To change the introduce() behavior we override the inherited method.
Accidental Overloading
Method overloading:
◦ Class has multiple methods with the same name, but different signatures.
◦ When Java is determining which constructor to call, the one that it calls is the one
with the same signature as the method call.
◦ If there is no method with the matching signature, then a method not found syntax
error occurs.
Common Error: If you intend to override, but change parameters, you will be
overloading the inherited method, not overriding it.
Object Class
In Java, every class that is declared without an explicit extends clause automatically
extends the class Object.
Object class implements the following methods:
o toString() : returns default String representation of an object.
o equals() : referential equality not data equality.
Every class we define automatically inherits these methods.
We should override these methods if we want to change their behaviors.
Accidental Overload – equals()
Inheritance and the equals Method
▪ Default equals signature: boolean equals( Object obj )
▪ Employee equals signature: boolean equals( Employee obj )
• What if someone called [Link](x) where x was not an Employee
object?
• Equals is overloaded and not overridden; Object equals method is called.
• Use instanceof or getClass() to ensure parameter is Employee.
public boolean equals(Object otherObject)
{
if (otherObject == null) { return false; }
if (getClass() != [Link]()) { return false; }
Employee other = (Employee) otherObject;
return [Link]([Link]);
}
Advantages of Inheritance
∙ Avoid code duplication – no need to write the same code twice, write it once
and then create classes that inherit the functionality.
∙ Code reuse – if a similar class already exists, we can create a subclass and
reuse existing code without having to write the code again.
∙ Easier maintenance – a change in a shared field/method needs only to be
made once, in the superclass, and it is automatically inherited by the
subclasses.
∙ Extendibility- it becomes easier to extend an existing application in certain
ways.
Object References - Substitution
To assign an object to a variable, the type of the object must match the type of the
variable.
A variable can reference an object of its own type, or of a subclass type.
◦ A reference of a super class type can reference an object of a subclass type. For
example, a reference of type Animal can reference Cat, or Dog objects. This is
because a Dog is-a Animal, and a Cat is-a Animal.
◦ We can substitute a subclass object where a superclass object is expected because
the subclass object is a special case of the superclass.
◦ The opposite is not possible.
Variables of a subclass type cannot reference super class objects.
◦ Subclasses may define data and methods that are not present in the super class.
◦ If we assign a super class object to a subclass reference, we would not be able to
access all data fields and methods of the subclass through the superclass reference.
Employee Example Employee
#empName
#empId
#salary
#taxRate
+getters and Setters
+calculatePay()
is-a is-a
CommissionEmployee
HourlyEmployee -totalSales
-hoursWorked -commissionRate
+calculatePay() +calculatePay()
+toString() +toString()
Payroll
Employee HourlyEmployee
CommissionEmployee
Example: Object Reference
Assume the following code is executed:
Object obj;
Employee anEmp = new Employee(“Sam”, “1111”);
HourlyEmployee hourEmp = new HourlyEmployee(“Sally”, “2222”);
CommissionEmployee commEmp = new CommissionEmployee(“Tony”, “2345”);
The following assignment is allowed:
obj = anEmp; // obj references an object of type Employee
anEmp = hourEmp;
Because obj is of type Object, only the methods and fields defined in Object can be accessed.
The following statement: [Link]() would be illegal, because there is no getName() method defined
in the class Object. [Link]() is a valid method call, because there is a toString() method
defined in the Object class.
If there is also a toString() method defined in the class Employee, it will execute because the object
referenced is an Employee object.
Example: Object Reference
A variable of a super class type can reference an object of a subclass type.
The opposite is not allowed.
With the declarations above, the following is an illegal assignment:
Employee anEmp = new Employee();
CommissionEmp commEmp = anEmp;
The two types are incompatible.
After assignment, commEmp would reference an instance of its super class.
We should be able to access all data fields and methods of class CommissionEmployee
through the variable commEmp, including data field annualSalary. Employee does not have
all these data fields.
Downcasting and Inheritance
A subclass object can be assigned to a superclass reference.
To use the fields and methods that belong to the subclass, we will need to first cast the
object to its correct type (downcasting).
Downcasting is allowed if the object anEmp is an HourlyEmployee, if not, an error would
occur.
Example:
//anEmp references an object of type HourlyEmployee
Employee anEmp = new HourlyEmployee(“Sam”, “1234”,…)
//Error – Employees do not have setHours() method.
[Link]( 25 );
//first downcast (cast to subclass type)
HourlyEmployee hourEmp = (HourlyEmployee) anEmp;
[Link](30.0);
Final Keyword
Final Data Member: creates the data member as a constant.
Final methods:
Cannot be overridden, overloading is allowed with final methods.
All subclasses use the same method implementation.
Calls to final methods are resolved at compile time (static binding). Program optimization.
Private methods: implicitly final, it is impossible to override them in a subclass, the subclass can
declare a new method with the same signature as the private method.
Static methods are implicitly final, cannot be overridden.
Final Classes:
A final class cannot be extended. All methods in a final class are implicitly final.
String class is an example of a final class
Polymorphism
Assume that we want to create a program to simulate the movements of different animals.
Program sends the same message to all Animal objects, telling them to move.
Each Animal responds to the message in a different way. A fish swims forward a meter; a bird
might fly forward 2 meters.
Program issues the same message to all animals, but each knows how to respond for its own type
of movement.
Polymorphism
Enables a particular method call to have different behaviour at different times.
Allows programmers to “program in the general” rather than “program in the specific”.
Programmers command objects to behave in manners appropriate to those objects without
knowing the specific types of the objects.
Each object knows how to do the correct thing, appropriate to its type.
Allows programmers to create easily extensible applications.
New classes can be added with little change to general application.
For example:
▪ if a new Animal, Tortoise, is added, the application that requests each Animal moves does
not change.
▪ We only need to create the new class, and the part where an instance of a tortoise is
created.
Dynamic Binding of Method Calls
Method calls are always determined by the type of the actual object, not the type of
the variable containing the object reference.
Called dynamic binding or dynamic method lookup.
Dynamic method lookup allows us to treat objects of different classes in a
uniform way.
We ask multiple objects to carry out a task, and each object does so in its own way.
Dynamic Binding Example
Example: [Link].
◦ Creates 3 different FarmAnimal objects,
◦ Stores those objects in array of type FarmAnimal.
◦ Using a loop calls each element’s, barnyard[i].makeSound() method to output the
sound.
◦ The makeSound() method call depends on the type of object referenced by barnyard[i].
Java cannot determine at compile time which makeSound() method to call because it does
not know at compile time what kind of FarmAnimal object will be referenced by each array
element.
At run-time, Java determines which makeSound() method to call based on the data type of
the object referenced by barnyard[i]. The object will be linked to the code for its
makeSound() method, and that is the one that executes.