Unit 3
Unit 3
Inheritance
Types of Inheritance:
1. Single Inheritance
2. Multilevel Inheritance
3. Hierarchical Inheritance
4. Multiple Inheritance
5. Hybrid Inheritance
Specialization: The child class is a special case of the parent class; in other words, the child
class is a subtype of the parent class.
Specification: The parent class defines behavior that is implemented in the child class but not
in the parent class.
Construction: The child class makes use of the behavior provided by the parent class, but is
not a subtype of the parent class.
Generalization: The child class modifies or overrides some of the methods of the parent
class.
Extension: The child class adds new functionality to the parent class, but does not change
any inherited behavior.
Limitation: The child class restricts the use of some of the behavior inherited from the
parent class.
Variance: The child class and parent class are variants of each other, and the class-subclass
relationship is arbitrary.
Combination: The child class inherits features from more than one parent class. This is
multiple inheritance and will be the subject of a later chapter.
1. Single Inheritance:
Class B Subclass
Class
Example:
class x
{
int a;
void display()
{
a=0;
System.out.println(a);
}
}
class y extends x
{
int b;
void show()
{
b=1;
System.out.println(b);
}
}
class show_main
{
public static void main(String args[])
{
y y1=new y(); // Create object of child class only
y1.display();
y1.show();
}
}
Output:
0
1
Since the class y is inheriting class x, it is able to access the members of class x. Hence the
method display() can be invoked by the instance of the class y.
2. Multilevel Inheritance:
Class B Intermediate
class
Since class z is inheriting class y which is in turn a sub class of the class x, indirectly z can
access the members of class x. Hence the instance of class z can access the display () method
in class x, the show () method in class y.
Example:
class A
{
void add()
{
int a, b, c; a=2; b=4;
System.out.println("Value C :"+ a+b);
}
}
class B extends A
{
void mul()
{
int a, b, c; a=2; b=4;
System.out.println("Value C :"+ a*b);
}
}
class C extends B
{
void div()
{
int a, b, c; a=4; b=2;
System.out.println("Value C :"+ a/b);
}
}
class Multilevel
{
public static void main(String[] args)
{
C ob=new C();
ob.add();
ob.mul();
ob.div();
}
}
Output:
Value C : 6
Value C : 8
Value C : 2
3. Hierarchical Inheritance:
One super class and more than one sub class it’s called hierarchical inheritance.
Class B Class C
Sub class
Example:
class A
{
int a, b, c;
void add()
{
a=2; b=4;
System.out.println("Value C :"+ a+b);
}
}
class B extends A
{
void mul()
{
a=2; b=4;
System.out.println("Value C :"+ a*b);
}
}
class C extends A
{
void div()
{
a=4; b=2;
System.out.println("Value C :"+ a/b);
}
}
class hierarchical
{
public static void main(String[] args)
{
B ob1=new B();
ob1.add();
ob1.mul();
C ob2=new C();
ob2.div();
}
}
Output:
6
8
2
4. Hybrid Inheritance
Hybrid inheritance is a type of inheritance. Hybrid inheritance is combination of both single
inheritance and multiple inheritance. In java, we cannot implement multiple inheritance using
classes.
Example:
class C
{
public void disp()
{
System.out.println("C");
}
}
class A extends C
{
public void disp()
{
System.out.println("A");
}
}
class B extends C
{
public void disp()
{
System.out.println("B");
}
}
class D extends A
{
public void disp()
{
System.out.println("D");
}
public static void main(String args[])
{
D obj = new D();
obj.disp();
}
}
Output:
D
5. Multiple Inheritance:
Java doesn’t support multiple inheritance. Suppose c is the child class extending from both parent
class a and parent class b with some methods defined in them. Then child class cannot understand
which class method to call. So there is a confusion here which leads to ambiguity and leads to compile
time error. This is the reason java doesn’t support multiple inheritance. Java doesn’t allow multiple
inheritance to avoid the ambiguity caused by it. One of the example of such problem is the diamond
problem that occurs in multiple inheritance.
We will discuss this problem with the help of the diagram below: which shows multiple inheritance
as Class D extends both classes B & C. Now lets assume we have a method in class A and class B &
C overrides that method in their own way. Wait!! here the problem comes – Because D is extending
both B & C so if D wants to use the same method which method would be called (the overridden
method of B or the overridden method of C). Ambiguity. That’s the main reason why Java doesn’t
support multiple inheritance.
Figure: Diamond Problem -Multiple
Inheritance
(Source: Beginnersbook.com)
Super keyword:
Whenever a sub class needs to refer to its immediate super class, we can use the super keyword.
• Super is a reference variable that is used to refer parent/super/base class objects.
• Super is a used to access variables, constructors and methods of a parent/super/base class.
• Super has two general forms:
➢ The first calls the super class constructor.
➢ The second is used to access a member of the super class that has been hidden by a
member of a sub class.
• A sub class can call a constructor defined by its super class by use of the following form of
• super.
super(arg-list);
• here arg-list specifies any arguments needed by the constructor in the super class .
• The second form of super acts like a this keyword.
• The difference between this and super is that this is used to refer the current object whereas
the super is used to refer to the super class.
Example:
public class car
{
int speed=200;
}
class bike extends car
{
int speed=100;
void display()
{
//super to access speed method of car class
System.out.println(super.speed);
System.out.println(speed);
}
}
class vehicle
{
public static void main(String args[])
{
bike ob=new bike();
ob.display();
}
}
output:
200
100
The syntax super.method_name() is used to call a method of the super class from the sub class.
class car
{
car()
{
System.out.println("Printed in car class.");
}
}
class bike extends car
{
bike()
{
super(); // here super keyword is to access constructor
of car(super) class
System.out.println("Printed in bike class");
}
}
class vehicle
{
public static void main(String[] args)
{
bike ob = new bike();
}
}
Output:
Printed in car class
Printed in bike class
Method Overriding:
When method in sub class has same name as a method in super class then method in sub class is said
to override the method in super class.
Advantage of Method Overriding
• Method Overriding is used to provide specific implementation of a method that is already
provided by its super class.
• Method Overriding is used for Runtime Polymorphism.
Rules for Method Overriding:
• Method must have same name as in the parent class.
• Method must have same parameter as in the parent class.
Example:
class Superclass
{
void print()
{
System.out.println("Printed in Superclass.");
}
}
class Subclass extends Superclass
{
void print() //Overriding
{
super.print();
System.out.println("Printed in Subclass");
}
public static void main(String[] args)
{
Subclass s = new Subclass();
s.print();
}
}
Output:
Printed in Superclass.
Printed in Subclass.
Example 2:
class A
{
int i,j;
A(int a,int b)
{
i=a;
j=b;
}
void show()
{
System.out.println(“i and j:”+i+” “+j);
}
}
class B extends A
{
int k;
B(int a,int b,int c)
{
super(a,b);
k=c;
}
void show()
{
super.show();
System.out.println("k:"+k);
}
}
class overriding
{
public static void main(String[] args)
{
B ob=new B(10,20,30);
ob.show ( );
}
}
Output:
i and j : 10 20
k:30
What is difference between overloading and overriding?
Sr.No Method overloading Method overriding
1 When two or more methods in a class When a method in a subclass has the same
have the same method names with method name with same arguments as that
different arguments, it is said to of the super class, it is said to be
be method overloading. method overriding.
2 Overloading does not block inheritance Overriding blocks inheritance from the
from the super class. super class.
3 In case of method overloading, In case of method overriding parameter
parameter must be different. must be same.
Interfaces:
Interfaces are designed to support dynamic method resolution at run time. An interface in java is a
blueprint of a class. It has static constants and abstract methods. The interface in Java is a mechanism
to achieve abstraction. There can be only abstract methods in the Java interface, not method body. It
is used to achieve abstraction and multiple inheritance in Java.
Why Interfaces:
Normally, in order for a method to be called from one class to another, both classes need to
be present at compile time so the Java compiler can check to ensure that the method signatures
are compatible. This requirement by itself makes for a static and no extensible classing
environment. Inevitably in a system like this, functionality gets pushed up higher and higher
in the class hierarchy so that the mechanisms will be available to more and more subclasses.
Interfaces are designed to avoid this problem. They disconnect the definition of a
method or set of methods from the inheritance hierarchy. Since interfaces are in a different
hierarchy from for classes classes, it is possible that are unrelated in terms of the class
hierarchy to implement the same interface. This is where the real power of interfaces is
realized.
Interfaces add most of the functionality that is required for many applications which
would normally resort to using multiple inheritance in a language such as C++.
Implementing Interfaces:
➢ Once an interface has been defined, one or more classes can implement that interface.
➢ To implement an interface, include the implements keyword in a class definition, and
then create the methods defined by the interface.
➢ The general form of a class that includes the implements clause looks like this:
Example:-1
interface I1
{
public int a=10; // final or constant variable
public int b=20;
public void sum(); // abstract method
}
class one implements I1
{
public void sum()
{
System.out.print("Sum-->"+(a+b));
}
}
class two
{
public static void main(String[] args)
{
one ob1=new one();
ob1.sum();
}
}
Output:
Sum--> 30
Example:-2
interface I1
{
public void show();
}
interface I2
{
public void show1();
}
class A implements I1,I2
{
public void show()
{
System.out.println("I am the implementation of
interface first");
}
public void show1()
{
System.out.println("I am the implementation of
interface second");
}
}
class interface1
{
public static void main(String[] args)
{
A a=new A();
a.show();
a.show1();
}
}
Output:
I am the implementation of interface first
I am the implementation of interface second
interface IntStack
{
void push(int item); // store an item
int pop(); // retrieve an item
}
The following program creates a class called FixedStack that implements a fixed-length
version of an integer stack:
System.out.println("Stack in mystack2:");
for(int i=0; i<8; i++)
System.out.println(mystack2.pop());
}
}
Output: Check yourself
Variables in Interfaces:
➢ Interfaces can be used to import shared constants into multiple classes by simply declaring an
interface that contains variables which are initialized to the desired values.
➢ When we include that interface in a class (that is, when you ―implement‖ the interface), all
of those variable names will be in scope as constants.
➢ This is similar to using a header file in C/C++ to create a large number of #defined constants
or const declarations.
➢ If an interface contains no methods, then any class that includes such an interface doesn‘t
actually implement anything. It is as if that class were importing the constant variables into
the class name space as final variables.
Example:
import java.util.Random;
interface SharedConstants
{
int NO = 0; int YES = 1;
int MAYBE = 2; int LATER = 3;
int SOON = 4; int NEVER = 5;
}
class Question implements SharedConstants
{
Random rand = new Random();
int ask()
{
int prob = (int) (100 * rand.nextDouble());
if (prob < 30)
return NO; // 30%
else if (prob < 60)
return YES; // 60%
else if (prob < 75)
return LATER; // 75%
else if (prob < 98)
return SOON; // 98%
else
return NEVER; // 2%
}
}
class AskMe implements SharedConstants
{
static void answer(int result)
{
switch(result)
{
case 0:
System.out.println("No"); break;
case 1:
System.out.println("Yes"); break;
case 2:
System.out.println("Maybe"); break;
case 3:
System.out.println("Later"); break;
case 4:
System.out.println("Soon"); break;
case 5:
System.out.println("Never"); break;
}
}
public static void main(String args[])
{
Question q = new Question();
answer(q.ask());
answer(q.ask());
answer(q.ask());
answer(q.ask());
}
}
Output:
Later
Soon
No
Yes
Nested Interfaces:
Example:
class A
{
// this is a nested interface
public interface NestedIF
{
boolean isNotNegative(int x);
}
}
// B implements the nested interface.
One interface can inherit another by use of the keyword extends. The syntax is the same as for
inheriting classes. When a class implements an interface that inherits another interface, it must
provide implementations for all methods required by the interface inheritance chain. Following is an
example:
Example:
// One interface can extend another.
interface A {
void meth1();
void meth2();
}
// B now includes meth1() and meth2() -- it adds meth3().
interface B extends A
{
void meth3();
}
// This class must implement all of A and B
class MyClass implements B
{
public void meth1()
{
System.out.println("Implement meth1().");
}
public void meth2()
{
System.out.println("Implement meth2().");
}
public void meth3()
{
System.out.println("Implement meth3().");
}
}
class Extend
{
public static void main(String arg[])
{
MyClass ob = new MyClass();
ob.meth1();
ob.meth2();
ob.meth3();
}
}
Output:
Implement meth1().
Implement meth2().
Implement meth3().
Abstract Class:
• A class that is declared with abstract keyword, is known as abstract class in java. It can have abstract
(No method body) and non-abstract methods (method with body).
• Abstraction is a process of hiding the implementation details and showing only functionality to the
user.
• Another way, it shows only important things to the user and hides the internal details for example
sending sms, you just type the text and send the message. You don't know the internal processing
about the message delivery.
• Abstraction lets you focus on what the object does instead of how it does it.
• There are two ways to achieve abstraction in java
1. Abstract class (0 to 100%)
2. Interface (100%)
• A class that is declared as abstract is known as abstract class. It needs to be extended and its
method implemented. It cannot be instantiated.
• A method that is declared as abstract and does not have implementation is known as abstract
method.
We can require that some methods be overridden by sub classes by specifying the abstract
type modifier. These methods are sometimes referred to as sub classer responsibility as they
have no implementation specified in the super class. Thus a sub class must override them.
Any class that contains one or more abstract methods must also be declared abstract.
Such types of classes are known as abstract classes. Abstract classes can contain both
abstract and non-abstract methods.
Let us consider the following example 1:
abstract class A
{
abstract void callme();
void call()
{
System.out.println(“HELLO”);
}
}
class B extends A
{
void callme()
{
System.out.println(“GOOD MORNING”);
}
}
class abstractdemo
{
Public static void main(String args[])
{
B b=new B();
b.callme();
b.call();
}
}
Output:
GOOD MORINING
HELLO
5) Abstract class can provide the Interface can't provide the implementation
implementation of interface. of abstract class.
6) The abstract keyword is used to declare The interface keyword is used to declare
abstract class. interface.
7) Example: Example:
public abstract class Shape public interface Drawable
{ {
public abstract void draw(); void draw();
} }
8)extends keyword is used to inherit a class. implements keyword is used to inherit and
interface.
9)Methods have to be tagged as public or abstract By default, all methods in an interface are
or both, if required public and abstract; no need to tag it as
public and abstract
10)Abstract classes can have partial Interfaces have no implementation at all.
implementation.
11)Only abstract methods need to be overridden. All methods of an interface need to be
overridden.
12)Variables, if required, have to be declared as All variables declared in an interface are by
public static or final. default public, static or final.
Polymorphism
Polymorphism in Java is a concept by which we can perform a single action in different ways.
Polymorphism is derived from 2 Greek words: poly and morphs. The word "poly" means many and
"morphs" means forms. So polymorphism means many forms.
There are two types of polymorphism in Java: compile-time polymorphism and runtime
polymorphism. We can perform polymorphism in java by method overloading and method
overriding.
If you overload a static method (Self Study) in Java, it is the example of compile time polymorphism.
Casting of Objects :-
1) Implicit casting
You have already used the casting operator to convert variables of one primitive type to
another. Casting can also be used to convert an object of one class type to another within an
inheritance hierarchy.
The statement
m(new Student());
assigns the object new Student() to a parameter of the Object type. This statement is equivalent to
Object o = new Student(); // Implicit casting
m(o);
The statement Object o = new Student(), known as implicit casting, is legal because
an instance of Student is automatically an instance of Object m.
2) Explicit casting
Suppose you want to assign the object reference o to a variable of the Student type using the
following statement:
Student b = o;
A compilation error would occur. Why does the statement Ob o = new Student() work and
the statement Student b = o doesn't? Because a Student object is always an instance of Ob, but an Ob
is not necessarily an instance of Student. Even though you can see that o is really a Student object,
the compiler is not clever enough to know it. To tell the compiler that o is a Student object, use an
explicit casting. The syntax is similar to the one used for casting among primitive data types. Enclose
the target object type in parentheses and place it before the object to be cast, as follows:
Syntax:
class A{}
class B extends A{}
A a=new B();//upcasting
Example 1
class Game
{
public void type()
{
System.out.println("Indoor & outdoor");
}
}
class Cricket extends Game
{
public void type()
{
System.out.println("outdoor game");
}
public static void main(String[] args)
{
Game gm = new Game();
Cricket ck = new Cricket();
gm.type();
ck.type();
gm=ck; //gm refers to Cricket object
gm.type(); //calls Cricket's version of type
}
}
Output :
Indoor & outdoor
Outdoor game
Outdoor game
Example 2:
class Bank
{
int getRateOfInterest()
{
return 0;
}
}
class SBI extends Bank
{
int getRateOfInterest(){return 8;}
}
class ICICI extends Bank
{
int getRateOfInterest(){return 7;}
}
class AXIS extends Bank
{
int getRateOfInterest(){return 9;}
}
class Test3
{
public static void main(String args[])
{
Bank b1=new SBI();
Bank b2=new ICICI();
Bank b3=new AXIS();
System.out.println("SBI ROI:"+b1.getRateOfInterest());
System.out.println("ICICI ROI:"+b2.getRateOfInterest());
System.out.println("AXIS ROI: "+b3.getRateOfInterest());
}
}
Output :
SBI ROI: 8
ICICI ROI: 7
AXIS ROI: 9
instanceof Operator:-
For the casting to be successful, you must make sure that the object to be cast is an instance
of the subclass. If the superclass object is not an instance of the subclass, a runtime
ClassCastException occurs. For example, if an object is not an instance of Student, it cannot be
cast into a variable of Student. It is a good practice, therefore, to ensure that the object is an instance
of another object before attempting a casting. This can be accomplished by using the instanceof
operator. Consider the following code:
Why not declare myObject as a Circle type in the first place? To enable generic programming,
it is a good practice to declare a variable with a supertype, which can accept a value of any subtype.
TestPolymorphismCasting.java
package chapter9;
public class TestPolymorphismCasting {
Output:
The program uses implicit casting to assign a Circle object to object1 and a Rectangle object
to object2 (lines 6–7), and then invokes the displayObject method to display the information on these
objects (lines 13–24).
In the displayObject method (lines 13–24), explicit casting is used to cast the object to Circle
if the object is an instance of Circle, and the methods getArea and getDiameter are used to display
the area and diameter of the circle.
Casting can only be done when the source object is an instance of the target class. The
program uses the instanceof operator to ensure that the source object is an instance of the target class
before performing a casting (line 14).
Explicit casting to Circle (lines 15, 17) and to Rectangle (line 22) is necessary because the
getArea and getDiameter methods are not available in the Object class.
Package in Java
Java provides a mechanism for partitioning the class name space into more manageable
chunks. This mechanism is the package. The package is both a naming and a visibility control
mechanism. You can define classes inside a package that are not accessible by code outside that
package. You can also define class members that are only exposed to other members of the same
package.
Advantages of Packages:
• Package is used to categorize the classes and interfaces so that they can be easily maintained.
• Package provides access protection.
• Package removes naming collision.
Defining a Package:
• Creating a package is quite easy: simply include a package command as the first statement in a
Java source file. Any classes declared within that file will belong to the specified package. The
package statement defines a name space in which classes are stored.
• If you omit the package statement, the class names are put into the default package, which has
no name. While the default package is fine for short, sample programs, it is inadequate for real
applications. Most of the time, you will define a package for your code.
Naming rules for packages:
Package names are written in all lowercase to avoid conflict with the names of classes or interfaces.
• The directory name must be same as the name of package that is created using "package" keyword
in the source file.
• Before running a program, the class path must be picked up till the main directory (or package)
that is used in the program.
• If we are not including any package in our java source file then the source file automatically goes
to the default package.
• In general, we start a package name begins with the order from top to bottom level.
• In case of the internet domain, the name of the domain is treated in reverse (prefix) order.
Creating a Package:
• To create a package, you choose a name for the package and put a package statement with that
name at the top of every source file that contains the types ( classes, and interfaces) that you want
to include in the package.
• The package statement (example-package graphics ;) must be the first line in the source file.
• There can be only one package statement in each source file, and it applies to all types in the file.
Example
package pack;
public class A
{
int i,j;
A(int x, int y)
{
i=x;
j=y;
}
display()
{
System.out.println("Addition:"+(i+j));
}
public static void main(String args[])
{
System.out.println("HELLO WORLD");
}
}
• compile your program like :- D:\>Java_prog\Package\javac –d . A.java
• This source file should be named A.java and stored in the sub directory
pack. Now compile this java file.
• The resultant A.class will be stored in the same sub directory.
import pack.A;
class B
{
public static void main(String args[])
{
A ob = new A(5,9);
ob.display();
}
}
• The source file should be saved as B.java and then compiled.
• The source file and the compiled file would be saved in the directory of which pack was a
subdirectory.
D:\>Java_prog\Package\javac B. java
D:\>Java_prog\Package\java B
Output:- 14
Example:
• This is file Protection.java:
package p1;
public class Protection
{
int n = 1;
private int n_pri = 2;
protected int n_pro = 3;
public int n_pub = 4;
public Protection()
{
System.out.println("base constructor");
System.out.println("n = " + n);
System.out.println("n_pri = " + n_pri);
System.out.println("n_pro = " + n_pro);
System.out.println("n_pub = " + n_pub);
}
}
• This is file Derived.java:
package p1;
class Derived extends Protection
{
Derived()
{
System.out.println("derived constructor");
System.out.println("n = " + n);
// class only
// System.out.println("n_pri = " + n_pri);
System.out.println("n_pro = " + n_pro);
System.out.println("n_pub = " + n_pub);
}
}
package p1;
class SamePackage
{
SamePackage()
{
Protection p = new Protection();
System.out.println("same package constructor");
System.out.println("n = " + p.n);
// class only
// System.out.println("n_pri = " + p.n_pri);
System.out.println("n_pro = " + p.n_pro);
System.out.println("n_pub = " + p.n_pub);
}
}
• This is file Protection2.java:
package p2;
class Protection2 extends p1.Protection
{
Protection2()
{ System.out.println("derived other package
constructor");
// class or package only
// System.out.println("n = " + n);
// class only
// System.out.println("n_pri = " + n_pri);
System.out.println("n_pro = " + n_pro);
System.out.println("n_pub = " + n_pub);
}
}
• If you wish to try these two packages, here are two test files you can use. The one
for package p1 is shown here:
// Demo package
p1. package p1;
// Instantiate the various classes in
p1. public class Demo
{
public static void main(String args[])
{
Protection ob1 = new Protection();
Derived ob2 = new Derived();
SamePackage ob3 = new SamePackage();
}
}
• The test file for p2 is shown next:
// Demo package
p2.package p2;
// Instantiate the various classes in p2.
public class Demo
{
public static void main(String args[])
{
Protection2 ob1 = new Protection2();
OtherPackage ob2 = new OtherPackage();
}
}
Java run-time system know where to look for packages that you create? The answer has two
parts.
• First, by default, the Java run-time system uses the current working directory as its starting
point. Thus, if your package is in the current directory, or a subdirectory of the current
directory, it will be found.
• Second, you can specify a directory path or paths by setting the CLASSPATH environmental
variable.
• For example, consider the following package specification.
package MyPack;
In order for a program to find MyPack, one of two things must be true. Either the
program is executed from a directory immediately above MyPack, or CLASSPATH must
be set to include the path to MyPack.
The first alternative is the easiest (and doesn‘t require a change to
CLASSPATH), but the second alternative lets your program find MyPack no matter what
directory the program is in.
Create the package directories below your current development directory, put the
.class files into the appropriate directories and then execute the programs from the
development directory.
Importing package
o In a Java source file, import statements occur immediately following the package statement
(if it exists) and before any class definitions.
o This is the general form of the import statement:
import pkg1[.pkg2].(classname.*);
o Here, pkg1 is the name of a top-level package, and pkg2 is the name of a subordinate package
inside the outer package separated by a dot (.).
o There is no practical limit on the depth of a package hierarchy, except that imposed by the
file system.
o Finally, you specify either an explicit classname or a star (*), which indicates that the Java
compiler should import the entire package.
o This code fragment shows both forms in use:
import java.util.Date;
import java.io.*;
Example:
package pack;
public class A
{ int a; int b;
A(int i,int j)
{
a=i; b=j;
}
public void display()
{
System.out.println(a + "&" + b);
}}