Module 3 Part 1 - Inheritance
Module 3 Part 1 - Inheritance
MODULE 3
Inheritance:
Inheritance Basics, Using super, Creating a Multilevel Hierarchy, When Constructors Are
Executed, Method Overriding, Dynamic Method Dispatch, Using Abstract Classes, Using final
with Inheritance, Local Variable Type Inference and Inheritance, The Object Class.
Interfaces:
Interfaces, Default Interface Methods, Use static Methods in an Interface, Private Interface
Methods.
Chapter 8, 9
TOPIC: INHERITANCE
Inheritance is one of the object-oriented principles that allows the creation of hierarchical
classifications. Using inheritance you can create a general class that defines traits common to a set
of related items. This class can be inherited by other, more specific classes, each adding those things
that are unique to it. A class that is inherited is called a superclass. The class that does the
inheriting is called the subclass. A subclass is a specialized version of a superclass. A subclass
inherits all of the instance variables and methods defined by the superclass and adds its own, unique
elements.
INHERITANCE BASICS:
To inherit a class, we need to incorporate the definition of one class into another by using the
extends keyword. The general form of a class declaration that inherits a superclass is
Example: The following program creates a superclass called A and a subclass called B.
class SimpleInheritance
{
public static void main(String args[ ])
{
A superOb = new A();
B subOb = new B();
The output:
Contents of superOb:
i and j: 10 20
Contents of subOb:
i and j: 7 8
k: 9
Although a subclass includes all of the members of its superclass, it cannot access those members of
the superclass that have been declared as private. In a class hierarchy, private members remain
private to their class.
Example Program
// This program contains an error and will not compile
// create a superclass
class A
{
int i; // public by default
private int j; // private to A
void setij(int x, int y)
{
i = x;
j = y;
}
}
// A's j is not accessible here
class B extends A
{
int total;
void sum ()
{
total = i + j; // Error: j is not accessible here
}
}
class Access
{
public static void main(String args[])
{
B subOb = new B();
subOb.setij(10,12);
subOb.sum();
System.out.println("Total is " + subOb.total);
}
}
Output:
$ javac Access.java
Access.java:18: error: j has private access in A
total = i + j; // Error: j is not accessible here
1 error
Note:
● The above program will not compile because the reference to j inside the sum() method of B
causes an access violation.
● Since j is declared as private, it is only accessible by other members of its own class.
Subclasses have no access to it.
● Hence, a class member that has been declared as private will remain private to its
class. It is not accessible by any code outside its class, including subclasses.
● In this example program the Box class is extended to include a fourth component called
weight.
● Hence the new class will contain a box’s width, height, depth and weight.
// create a superclass
class Box
{
double width;
double height;
double depth;
class DemoBoxWeight
{
public static void main(String args[])
{
BoxWeight mybox1 = new BoxWeight(10, 20, 15, 34.3);
BoxWeight mybox2 = new BoxWeight(2, 3, 4, 0.076);
double vol;
vol = mybox1.volume();
System.out.println("Volume of mybox1 is " + vol);
System.out.println("Weight of mybox1 is " + mybox1.weight);
vol = mybox2.volume();
System.out.println("Volume of mybox2 is " + vol);
System.out.println("Weight of mybox2 is " + mybox2.weight);
}
}
Output:
$ javac DemoBoxWeight.java
$ java DemoBoxWeight
Volume of mybox1 is 3000.0
Weight of mybox1 is 34.3
Volume of mybox2 is 24.0
Weight of mybox2 is 0.076
Note:
● BoxWeight inherits all of the characteristics of Box and adds to them the weight component.
● It is not necessary for BoxWeight to re-create all of the features found in Box. It can simply
extend Box to meet its own purposes.
Advantage of Inheritance:
● The major advantage of inheritance is that once you have created a superclass that defines
the attributes common to a set of objects, it can be used to create any number of more
specific subclasses.
● Each subclass can precisely tailor its own classification.
● Once a superclass is created that defines the general aspects of an object, that superclass can
be inherited to form specialized classes. Each subclass simply adds its own unique attributes.
This is the essence of inheritance.
In java programming, multiple and hybrid inheritance is supported through interface only.
When one class inherits multiple classes, it is known as multiple inheritance. Multiple inheritance is
not supported in Java through class.
1. Single Inheritance
When a class inherits another class, it is known as a single inheritance. In the example given below,
Dog class inherits the Animal class, so there is the single inheritance.
class Animal
{
void eat()
{
System.out.println("eating...");
}
}
class Dog extends Animal
{
void bark()
{
System.out.println("barking...");
}
}
class TestInheritance
{
public static void main(String args[])
{
Dog d=new Dog();
d.bark();
d.eat();
}
}
2. Multilevel Inheritance
When there is a chain of inheritance, it is known as multilevel inheritance. In the example given
below, BabyDog class inherits the Dog class which again inherits the Animal class, so there is a
multilevel inheritance.
class Animal
{
void eat()
{
System.out.println("eating...");
}
}
class TestInheritance2
{
public static void main(String args[])
{
BabyDog d=new BabyDog();
d.weep();
d.bark();
d.eat();
}
}
3. Hierarchical Inheritance
When two or more classes inherit a single class, it is known as hierarchical inheritance. In the
example given below, Dog and Cat classes inherit the Animal class, so there is hierarchical
inheritance.
class Animal{
void eat(){
System.out.println("eating...");
}
}
● A subclass can call a constructor defined by its superclass by use of the following form of
super:
super(arg-list);
Here, arg-list specifies any arguments needed by the constructor in the superclass.
● super() must always be the first statement executed inside a subclass’ constructor.
// create a superclass
class Box {
double width;
double height;
double depth;
// default constructor
BoxWeight() {
super();
weight = -1;
}
// Constructor used when cube is created
BoxWeight(double len, double m) {
super(len);
weight = m;
}
class Super {
public static void main(String args[]) {
BoxWeight mybox1 = new BoxWeight(10, 20, 15, 34.3);
BoxWeight mybox2 = new BoxWeight(2, 3, 4, 0.076);
BoxWeight mybox3 = new BoxWeight(); // default
BoxWeight mycube = new BoxWeight(3, 2);
BoxWeight myclone = new BoxWeight(mybox1);
double vol;
vol = mybox1.volume();
System.out.println("Volume of mybox1 is " + vol);
System.out.println("Weight of mybox1 is " + mybox1.weight);
System.out.println();
vol = mybox2.volume();
System.out.println("Volume of mybox2 is " + vol);
System.out.println("Weight of mybox2 is " + mybox2.weight);
System.out.println();
vol = mybox3.volume();
System.out.println("Volume of mybox3 is " + vol);
System.out.println("Weight of mybox3 is " + mybox3.weight);
System.out.println();
vol = myclone.volume();
System.out.println("Volume of myclone is " + vol);
System.out.println("Weight of myclone is " + myclone.weight);
System.out.println();
vol = mycube.volume();
System.out.println("Volume of mycube is " + vol);
System.out.println("Weight of mycube is " + mycube.weight);
System.out.println();
}
}
Output:
$ javac Super.java
$ java Super
Volume of mybox1 is 3000.0
Weight of mybox1 is 34.3
Volume of mybox2 is 24.0
Weight of mybox2 is 0.076
Note:
1. In the above program, BoxWeight() calls super() with the arguments w, h and d.
2. This causes the Box() constructor to be called, which Initializes width, height and depth
using these values.
3. BoxWeight no longer initialized these values itself.
4. It only needs to initialize the value unique to it, that is weight.
5. Since constructors can be overloaded, super() can be called using any form defined by the
superclass. The constructor executed will be the one that matches the argument.
Key points to remember:
● super() always refers to the superclass immediately above the calling class.
● super() must always be the first statement executed inside a subclass constructor.
● The second form of super always refers to the superclass of the subclass in which it is used.
void show() {
System.out.println("i in superclass: " + super.i);
System.out.println("i in subclass:" + i);
}
}
class UseSuper {
public static void main(String args[]) {
B subOb = new B(1,2);
subOb.show();
}
}
Output:
$ javac UseSuper.java
$ java UseSuper
i in superclass: 1
i in subclass:2
An example program to demonstrate all the uses of the keyword super. This program can be written
in exam as it demonstrates all the uses of the keyword super. Don’t forget to write the comments
mentioned in the program.
class Vehicle
{
int MaxSpeed;
Vehicle()
{
MaxSpeed = 120;
}
Vehicle(int s)
{
MaxSpeed = s;
}
void DisplaySpeed()
{
System.out.println("Speed of vehicle :" + MaxSpeed);
}
}
class DemoVehicle
{
public static void main(String args[])
{
Car carobj1 = new Car();
Car carobj2 = new Car(200);
carobj1.DisplaySpeed();
carobj2.DisplaySpeed();
}
}
Output:
$ javac DemoVeh.java
$ java DemoVeh
Speed of vehicle :120
Speed of Car: 180
Speed of vehicle :200
Speed of Car: 200
Program Explanation:
Program:
// create a superclass
class Box {
double width;
double height;
double depth;
// default constructor
BoxWeight() {
super();
weight = -1;
}
// default constructor
Shipment () {
super();
cost = -1;
}
class DemoShipment {
public static void main (String args[]) {
Shipment shipment1 = new Shipment(10, 20, 15, 10, 3.41);
Shipment shipment2 = new Shipment(2, 3, 4, 0.76, 1.28);
double vol;
vol = shipment1.volume();
System.out.println("Volume of Shipment is " + vol);
System.out.println("Weight of Shipment is " + shipment1.weight);
System.out.println("Shipping cost: $" + shipment1.cost);
System.out.println();
vol = shipment2.volume();
System.out.println("Volume of Shipment is " + vol);
System.out.println("Weight of Shipment is " + shipment2.weight);
System.out.println("Shipping cost: $" + shipment2.cost);
System.out.println();
}
}
Output:
$ javac DemoShipment.java
$ java DemoShipment
Volume of Shipment is 3000.0
Weight of Shipment is 10.0
Shipping cost: $3.41
class CallingCons {
public static void main(String args[]) {
C c = new C();
}
}
Output:
$ javac CallingCons.java
$ java CallingCons
Inside A's constructor.
Inside B's constructor.
Inside C's constructor.
Example Program:
// method overriding
class A {
int i, j;
A (int a, int b) {
i = a;
j = b;
}
// display i and j
void show() {
System.out.println("i = " + i + "j = " + j);
}
}
class B extends A {
int k;
B (int a, int b, int c) {
super(a, b);
k = c;
}
class Override {
public static void main(String args[]) {
B subOb = new B (1, 2, 3);
Output:
$ javac Override.java
$ java Override
i=1 j=2
k=3
Note:
● When show() is invoked on an object of type B, the version of show() defined
within B is used. That is, the version of show() inside B overrides the version
declared in A.
● If we want to access the superclass version of an overridden method, we can do
by using super. For example, in the above program, the superclass version of
show() is invoked within the subclass’ version. This allows all instance
variables to be displayed.
● Super.show() calls the superclass version of show().
● Method overriding occurs only when the names and type signature of the
two methods are identical. If they are not, then the two methods are
simply overloaded.
● Java uses the fact “a superclass reference variable can refer to a subclass object, to
resolve calls to overridden methods at run time.
● When an overridden method is called by a reference, java determines which version of that
method to execute based on the type of object it refers to.
● It is the type of the object being referred to not the type of reference variable that
determines which version of an overridden method will be executed.
class B extends A {
// override callme()
void callme () {
System.out.println("Inside B's callme method");
}
}
class C extends A {
// override callme()
void callme() {
System.out.println("Inside C's callme method");
}
}
class Dispatch {
public static void main(String args[]) {
A a = new A(); // object of type A
B b = new B(); // object of type B
C c = new C(); // object of type C
A r; // obtain a reference of type A
r = a; // r refers to an A object
r.callme(); // Calls A's version of callme()
r = b; // r refers to a B object
r.callme(); // Calls B's version of callme()
r = c; // r refers to a C object
r.callme(); // Calls C's version of callme()
}
}
Output:
$ javac Dispatch.java
$ java Dispatch
Inside A's callme method
Inside B's callme method
Inside C's callme method
Program Explanation:
● This program creates one superclass called A and two subclasses of it B and C.
● The program then in turn assigns a reference to each type of object to r and
uses that reference to invoke callme().
● The version of callme() executed is determined by the type of object being
referred to at the time of call.
double area() {
System.out.println("Area of figure is undefined.");
return 0;
}
}
double area() {
System.out.println("Area of Rectangle.");
return dim1 * dim2;
}
}
class FindAreas {
public static void main(String args[]) {
Figure f = new Figure(10, 10);
Rectangle r = new Rectangle(9, 5);
Triangle t = new Triangle(10, 8);
Figure figref;
figref = r;
System.out.println("Area is " + figref.area());
figref = t;
System.out.println("Area is " + figref.area());
figref = f;
System.out.println("Area is " + figref.area());
}
}
Output:
$ javac FindAreas.java
$ java FindAreas
Area of Rectangle.
Area is 45.0
Area of Triangle
Area is 40.0
Area of figure is undefined.
Area is 0.0
Program Explanation:
● The program creates a superclass called Figure that stores the dimensions of a
two-dimensional object.
● It also defines a method called area() that computes the area of an object.
Abstract Class:
● Any class that contains one or more abstract methods must also be declared
abstract.
● To declare a class abstract, use the abstract keyword in front of the class
keyword at the beginning of the class declaration.
● A class which is declared with the abstract keyword is known as an
abstract class in Java. It can have abstract and non-abstract methods
(method with the body).
● There can be no objects of an abstract class. That is, an abstract class cannot
be directly instantiated with the new operator. Such objects would be
useless, because an abstract class is not fully defined.
● Also, we cannot declare abstract constructors, or abstract static methods.
● Any subclass of an abstract class must either implement all of the abstract
methods in the superclass, or be itself declared abstract.
class B extends A {
void callme() {
System.out.println("B's implementation of callme");
}
}
class AbstractDemo {
public static void main(String args[]) {
B b = new B();
b.callme();
b.callmetoo();
}
}
Output:
$ javac AbstractDemo.java
$ java AbstractDemo
B's implementation of callme
This is a concrete method
Note:
● No objects of class A are declared in the program.
class AbstractAreas {
public static void main(String args[])
{
// Figure r = new Figure(10,10); // illegal now
Rectangle r = new Rectangle(9, 5);
Triangle t = new Triangle(10, 8);
figref = r;
System.out.println("Area is " + figref.area());
figref = t;
System.out.println("Area is " + figref.area());
}
}
Output:
$ javac AbstractAreas.java
$ java AbstractAreas
Area of Rectangle.
Area is 45.0
Area of Triangle
Area is 40.0
● This means that you must initialize a final variable when it is declared.
● For example:
final int FILE_NEW = 1;
final int FILE_OPEN = 2;
final int FILE_SAVE = 3;
final int FILE_SAVEAS = 4;
final int FILE_QUIT = 5;
● Subsequent part of the program can now use FILE_OPEN, etc., as if they
were constants.
It is a common coding convention to choose all uppercase identifier for final
variables.
● Variable declared as final do not occupy memory on a per-instance basis.
Thus, a final variable is essentially a constant.
2. To prevent overriding:
● To disallow a method from being overridden, specify final as a modifier at the
start of its declaration.
● Methods declared as final cannot be overridden.
class A {
final void meth() {
System.out.println(“This is a final method”);
}
class B extends A {
void meth() { // error can’t override.
System.out.println(“Illegal”);
}
}
● Because meth() is declared as final, it cannot be overridden in B. If you attempt
to do so, a compile-time error will result.
● Methods declared as final can sometimes provide a performance
enhancement. The compiler is free to inline calls to them because it “knows”
they will not be overridden by a subclass.
● When a small final method is called, often the Java compiler can copy the
bytecode for the subroutine directly inline with the compiled code of the
calling method, thus eliminating the costly overhead associated with a method
call.
● Inlining is only an option with final methods.
3. To prevent inheritance:
● Sometimes we don’t want a class from being inherited. To do this, precede the
class declaration with final.
● Declaring a class as final implicitly declares all of its methods a final, too.
● It is illegal to declare a class as both abstract and final since the abstract
class is incomplete by itself and relies upon its subclasses to provide complete
implementations.
● Example
final class A {
// …
}
There is one special class, Object, defined by Java. All other classes are subclasses of
Object. That is, Object is a superclass of all other classes. This means that a reference
variable of type Object can refer to an object of any other class. Also, since arrays are
implemented as classes, a variable of type Object can also refer to any array.
Object defines the following methods, which means that they are available in every
object.
The methods getClass( ), notify( ), notifyAll( ), and wait( ) are declared as final. You may
override the others. These methods are described elsewhere in this book. However, notice
two methods now: equals( ) and toString( ). The equals( ) method compares the contents
of two objects. It returns true if the objects are equivalent, and false otherwise. The precise
definition of equality can vary, depending on the type of objects being compared. The
toString( ) method returns a string that contains a description of the object on which it is
called. Also, this method is automatically called when an object is output using println( ).
Many classes override this method. Doing so allows them to tailor a description specifically
for the types of objects that they create.
Overriding Overloading
Implements “runtime polymorphism” Implements “compile time polymorphism”
The method call is determined at runtime based The method call is determined at compile time
on the object type
Occurs between superclass and subclass Occurs between the methods in the same
class
Have the same signature (name and method Have the same name, but the parameters are
arguments) different
On error, the effect will be visible at runtime On error, it can be caught at compile time
class Overloading {
int add (int a, int b)
{
return a+b;
}
int add (int a, int b, int c)
{
return a+b+c;
}
}
class Animal {
void eat() {
System.out.println("eating...");
}
}
class Dog extends Animal {
void eat()
{
System.out.println("eating bread...");
}
}