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

Module 3 Part 1 - Inheritance

Uploaded by

ishitarani.2005
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

Module 3 Part 1 - Inheritance

Uploaded by

ishitarani.2005
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 32

OOP With JAVA

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

class subclass-name extends superclass-name


{
// Body of the class
}

Example: The following program creates a superclass called A and a subclass called B.

// A simple example of inheritances


// Create a superclass
class A
{
int i,j;
void showij()
{
System.out.println(“i and j : “ + i + “ “ + j);
}
}

// Create a subclass by extending class A


class B extends A
{
int k;
void showk()
{
System.out.println(“k: “ + k);
}
void sum()
{
System.out.println(“i+j+k: “ + (i+j+k));
}
}

class SimpleInheritance
{
public static void main(String args[ ])
{
A superOb = new A();
B subOb = new B();

// The superclass may be used by itself


superOb.i = 10;
superOb.j = 20;
System.out.println(“Contents of SuperOb: “);
superOb.showij();
System.out.println();

/* The subclass has access to all public members


of its superclass */
subOb.i = 7;
subOb.j = 8;
subOb.k = 9;
System.out.println(:”Contents of subOb :”);
subOb.showij();
subOb.showk();
System.out.println();

System.out.println(“Sum of i, j and k in subOb :”);


subOb.sum();
}
}

The output:
Contents of superOb:
i and j: 10 20

Contents of subOb:
i and j: 7 8
k: 9

Sum of i, j and k in subOb:


i+j+k:24
The subclass B includes all the members of its superclass A. Hence subOb can access i and j and
call showij(). Inside sum(), i and j can be referred to directly, as if they were part of B. Even though
A is a superclass for B, it is completely independent, stand-alone class. A subclass can be a
superclass for another subclass. We can only specify one superclass for any subclass that we create.
Java does not support the inheritance of multiple super classes into a single subclass. We can
create a hierarchy of inheritance in which a subclass becomes a superclass of another subclass.
However, no class can be a superclass of itself.

MEMBER ACCESS AND INHERITANCE

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.

A more practical example to illustrate the power of inheritance:

● 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.

// This program uses inheritance to extend Box.

// create a superclass
class Box
{
double width;
double height;
double depth;

// construct clone of an object


Box(Box ob)
{ // pass object to constructor
width = ob.width;
height = ob.height;
depth = ob.depth;
}

// constructor used when all dimensions specified


Box (double w, double h, double d)
{
width = w;
height = h;
depth = d;
}

// Constructor when no dimensions specified


Box ()
{
width = -1;
height = -1;
depth = -1;
}

// Constructor used when cube is created


Box ( double len)
{
width = height = depth =len;
}

// Compute and return volume


double volume()
{
return height * depth * width;
}
}

// Here, Box is extended to include weight


class BoxWeight extends Box
{
double weight; // weight of Box

// constructor for Boxweight


BoxWeight (double w, double h, double d, double m)
{
width = w;
height = h;
depth = d;
weight = m;
}
}

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.

Types of inheritance in java

On the basis of class, there can be three types of inheritance in java:


1. single,
2. multilevel and
3. hierarchical.

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 Dog extends Animal


{
void bark()
{
System.out.println("barking...");
}
}

class BabyDog extends Dog


{
void weep()
{
System.out.println("weeping...");
}
}

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...");
}
}

class Dog extends Animal{


void bark(){
System.out.println("barking...");
}
}

class Cat extends Animal{


void meow(){
System.out.println("meowing...");
}
}
class TestInheritance3{
public static void main(String args[]){
Cat c=new Cat();
c.meow();
c.eat();
//c.bark(); //C.T.Error
}
}

TOPIC: USING super


● Whenever a subclass needs to refer to its immediate superclass, it can do so by the use of the
keyword super.
● super has two general forms:
1. The first calls the superclass’ constructor.
2. The second is used to access a member of the superclass that has been hidden by
member of a subclass.

1. Using super to call superclass constructors:

● 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.

● Example program to demonstrate the use of super:

// Example program to demonstrate super

// create a superclass
class Box {
double width;
double height;
double depth;

//Construct clone of an object


Box(Box ob) { // pass object to constructor
width = ob.width;
height = ob.height;
depth = ob.depth;
}

// constructor used when all dimensions specified


Box (double w, double h, double d) {
width = w;
height = h;
depth = d;
}

// Constructor when no dimensions specified


Box () {
width = -1;
height = -1;
depth = -1;
}

// Constructor used when cube is created


Box ( double len) {
width = height = depth =len;
}

// Compute and return volume


double volume() {
return height * depth * width;
}
}

// Here, Box is extended to include weight


class BoxWeight extends Box {
double weight; // weight of Box

// construct clone of an object


BoxWeight(BoxWeight ob) { // pass object to constructor
super(ob);
weight = ob.weight;
}

// constructor when all parameters are specified


BoxWeight (double w, double h, double d, double m) {
super(w,h,d);
weight = m;
}

// 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

Volume of mybox3 is -1.0


Weight of mybox3 is -1.0

Volume of myclone is 3000.0


Weight of myclone is 34.3

Volume of mycube is 27.0


Weight of mycube is 2.0

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.

● This is true even in multilevel hierarchy.

● super() must always be the first statement executed inside a subclass constructor.

2. Second use of super to access a member of the superclass:

● The second form of super always refers to the superclass of the subclass in which it is used.

● The general form is:


super.member
Here, member can be either a method or an instance variable.
● The second form of super is most applicable to situations in which member names of a
subclass hide members by the same name in the superclass.
● Example program to demonstrate second use of superclass

// using super to overcome name hiding


class A {
int i;
}

// create a subclass by extending class A


class B extends A {
int i; // this i hides i in A
B(int a, int b) {
super.i = a; // i in A
i = b; // i in B
}

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 Car extends Vehicle


{
int MaxSpeed; // Data member with the same name as that of superclass
Car()
{
super(); // super is used to invoke the constructor of parent class
MaxSpeed = 180;
}
Car (int s)
{
super.MaxSpeed = s;// use of super to access the data member of parent class
MaxSpeed = s;
}
void DisplaySpeed() // Method name same as that of the superclass
{
super.DisplaySpeed(); // use of super to access the method of parent class
System.out.println("Speed of Car: " + 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

TOPIC: Creating a Multilevel Hierarchy


● We can build hierarchies that contain as many layers of inheritance as we need.

● We can use a subclass as a superclass of another. For example, given three


classes A, B and C, C can be a subclass of B, which in turn is a subclass of A.
● In this situation, each subclass inherits all of the traits found in all of its
superclasses. C inherits all aspects of B and A.

Example program to demonstrate multilevel hierarchy:

Program Explanation:

● The subclass BoxWeight is used as a superclass to create the Shipment


subclass.
● Shipment inherits all of the traits of BoxWeight and Box and adds a field
called cost, which holds the cost of shipping such a parcel.

Program:

// Example program to demonstrate multilevel hierarchy

// create a superclass
class Box {
double width;
double height;
double depth;

// construct clone of an object


Box(Box ob) { // pass object to constructor
width = ob.width;
height = ob.height;
depth = ob.depth;
}

// constructor used when all dimensions specified


Box (double w, double h, double d) {
width = w;
height = h;
depth = d;
}

// Constructor when no dimensions specified


Box () {
width = -1;
height = -1;
depth = -1;
}

// Constructor used when cube is created


Box ( double len) {
width = height = depth =len;
}

// Compute and return volume


double volume() {
return height * depth * width;
}
}

// Here, Box is extended to include weight


class BoxWeight extends Box {
double weight; // weight of Box

// construct clone of an object


BoxWeight(BoxWeight ob) { // pass object to constructor
super(ob);
weight = ob.weight;
}

// constructor when all parameters are specified


BoxWeight (double w, double h, double d, double m) {
super(w,h,d);
weight = m;
}

// default constructor
BoxWeight() {
super();
weight = -1;
}

// Constructor used when cube is created


BoxWeight(double len, double m) {
super(len);
weight = m;
}

// Add shipping costs


class Shipment extends BoxWeight {
double cost;

// construct clone of an object


Shipment(Shipment ob) {
super (ob);
cost = ob.cost;
}

// constructor when all parameters are specified


Shipment (double w, double h, double d, double m, double c) {
super(w,h,d,m);
cost = c;
}

// default constructor
Shipment () {
super();
cost = -1;
}

// constructor used when cube is created


Shipment(double len, double m, double c) {
super (len,m);
cost = c;
}
}

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

Volume of Shipment is 24.0


Weight of Shipment is 0.76
Shipping cost: $1.28

TOPIC: When Constructors are Called:


● In a class hierarchy, constructors are called in order of derivation, from superclass to
subclass.
● Also, since super() must be the first statement executed in a subclass’ constructor, this order
is the same whether or not super() is used.
● If super() is not used, then the default or parameterless constructor of each superclass will be
executed.

Program to illustrate when constructors are executed:

// demonstrate when constructors are called


class A {
A() {
System.out.println("Inside A's constructor.");
}
}
// Create a subclass by extending class A
class B extends A {
B() {
System.out.println("Inside B's constructor.");
}
}

// Create another subclass by extending B


class C extends B {
C() {
System.out.println("Inside C's constructor.");
}
}

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.

TOPIC: Method Overriding


● In a class hierarchy, when a method in a subclass has the same name and type
signature as a method in its superclass, then the method in the subclass is said
to override the method in the superclass.
● When an overridden method is called from within a subclass, it will always
refer to the version of that method defined by the subclass.
● The version of the method defined by the superclass will be hidden.

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;
}

// Display k - this overrides show() in A


void show () {
super.show(); // this calls A's show()
System.out.println("k = " + k);
}
}

class Override {
public static void main(String args[]) {
B subOb = new B (1, 2, 3);

subOb.show(); // this calls show in B


}
}

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.

TOPIC: Dynamic Method Dispatch:


● Dynamic method dispatch is the mechanism in which a call to an overridden method is
resolved at run time, rather than compile time.

● 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.

● Therefore, if a superclass contains a method that is overridden by a subclass, then


when different types of objects are referred to through a superclass reference variable,
different versions of the method are executed.

Pictorial representation of dynamic method dispatch


Example program to demonstrate dynamic method dispatch:

// Dynamic method dispatch


class A {
void callme () {
System.out.println("Inside A's callme method");
}
}

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.

● Subclasses B and C override callme() declared in A.

● inside the main() method, objects of type A, B and C are declared.

● Also, a reference of type A, called r is declared.

● 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.

Difference between Static binding and Dynamic binding in Java?

Applying Method Overriding:

// using run-time polymorphism


class Figure {
double dim1;
double dim2;

Figure (double a, double b) {


dim1 = a;
dim2 = b;
}

double area() {
System.out.println("Area of figure is undefined.");
return 0;
}
}

class Rectangle extends Figure {


Rectangle (double a, double b) {
super(a, b);
}

double area() {
System.out.println("Area of Rectangle.");
return dim1 * dim2;
}
}

class Triangle extends Figure {


Triangle(double a, double b) {
super(a, b);
}
double area() {
System.out.println("Area of Triangle");
return ( dim1 * dim2) / 2;
}
}

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.

● The program derives two subclasses from Figure.

● The first is Rectangle and the second is Triangle.

● Each of these subclasses overrides area() so that it returns the area of a


rectangle and a triangle respectively.
● Through the dual mechanism of inheritance and run-time polymorphism, it is
possible to define one consistent interface that is used by several different, yet
related, types of objects.
● The interface to this operation is same no matter what type of figure is being
used.

TOPIC: Using Abstract Classes


Abstract Method:
● Sometimes you want to create a superclass that only defines a generalized form
that will be shared by all of its subclasses, leaving it to each subclass to fill in
the details. In this case, we must ensure that a subclass must override all
necessary methods. Java’s solution to this is the abstract method.
● We can specify that certain methods must be overridden by subclasses by
specifying the abstract type modifier.
● These methods are sometimes referred to as sub-classer responsibility
because they have no implementation specified in the superclass. Hence, a
subclass must override them.
● To declare an abstract method, the general form is
abstract return_type method_name (parameter-list);
● An abstract method has no method body.
● A method that is declared as abstract and does not have implementation is
known as an abstract method.

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.

Example program to demonstrate abstract classification

// A simple demonstration of abstract


abstract class A {
abstract void callme();

// concrete methods are still allowed in abstract classes


void callmetoo() {
System.out.println("This is a concrete method");
}
}

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.

● It is not possible to instantiate an abstract class, but it is possible to create


a reference to an abstract class so that it can be used to point to a subclass
object.
● Class A implements a concrete method called callmetoo(), abstract classes can
include concrete methods too.
Example program – improved version of Figure classification

// using abstract methods and classes


abstract class Figure {
double dim1;
double dim2;

Figure (double a, double b) {


dim1 = a;
dim2 = b;
}
// area is now an abstract method
abstract double area();
}
class Rectangle extends Figure {
Rectangle (double a, double b) {
super(a, b);
}

// override area for Rectangle


double area() {
System.out.println("Area of Rectangle.");
return dim1 * dim2;
}
}

class Triangle extends Figure {


Triangle(double a, double b) {
super(a, b);
}
// override area for triangle
double area() {
System.out.println("Area of Triangle");
return ( dim1 * dim2) / 2;
}
}

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);

Figure figref; // this is ok, no object is created

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

TOPIC: Using final with Inheritance


● The keyword final has three uses
1. It can be used to create the equivalent of a named constant.
2. It can be used to prevent overriding
3. It can be used to prevent inheritance.

1. To create the equivalent of a named constant:


● A variable can be declared as final.

● Doing so prevents its contents from being modified.

● 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.

● The following fragment illustrates final

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.

● Normally, Java resolves calls to methods dynamically, at run time. This is


called late binding.
● However, since final methods cannot be overridden, a call to one can be
resolved at compile time. This is called early binding.

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 {
// …
}

// The following class is illegal


class B extends A { // Error: Can’t inherit A
// …
}

TOPIC: The Object class

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.

Difference between final, finally and finalize

Comparing overriding and overloading

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

Example program for overloading

class Overloading {
int add (int a, int b)
{
return a+b;
}
int add (int a, int b, int c)
{
return a+b+c;
}
}

Example program of overriding

class Animal {
void eat() {
System.out.println("eating...");
}
}
class Dog extends Animal {
void eat()
{
System.out.println("eating bread...");
}
}

You might also like