Java 3
Java 3
class Bird
{
public void eat()
{
System.out.println("All birds eat for their metabolic
activities");
}
}
public class Parrot extends Bird
{
public static void main(String args[])
{
Parrot p1 = new Parrot();
p1.eat();
}
}
You observe one new keyword "extends" in the above code; Parrot extends
Bird. By extending Bird class, Parrot can create an object of itself and
call eat() method of Bird. By extending, Parrot makes a relationship with
Bird. This relationship is known as "inheritance". The class which
extends is known as subclass (or derived class) and the class getting
extended is known as super class (or base class). Bird is called as base
class and Parrot is known as derived class. Observe the next program
where a subclass uses both composition and inheritance.
class Bird
{
String mouth = "red";
public void eat()
{
System.out.println("All birds eat for their metabolic
activities");
}
}
public class Parrot extends Bird
{
String body = "green";
public void food()
{
System.out.println("Parrot eats seeds and fruits");
}
public static void main(String args[])
{
Parrot p1 = new Parrot();
// calling its own members with its object
System.out.println(p1.body);
p1.food();
// calling super class members with its
object; inheritance
System.out.println(p1.mouth);
p1.eat();
// calling super class members with super
class object; composition
Bird b1 = new Bird();
System.out.println(b1.mouth);
b1.eat();
}
}
In the above code, the Parrot class uses both composition (as b1.eat())
and inheritance (as p1.eat()) to use super class members.
Java Extends:::
An OOPs language is meant more for reusability. It achieves reusability
with "has-a" relation (through composition) and "is-a" relation (through
inheritance). For "has-a" relationship, known as composition in Java,
refer Composition – "has-a" Relationship. Now let us discuss inheritance
and how the reusability is achieved. To get the concept, very small
programs are given.
Before going into the discussion, you are expected to know what a class
is in Java and the syntax of writing a Java class. This you can get from
What is a class in Java? and if you would like to know from the beginning
know from, Java for Beginners.
Because Ostrich is a bird and also can walk, I must write a method called
walk() in Ostrich class because Ostrich does not have the method. Yes,
you and everyone accept. OOPs comes into play here. OOPs is meant for
reusability, I told earlier. OOPs says, do not write, I give a solution
for it.
OOPs says, connect Ostrich with Bird so that Ostrich can use Bird’s
walk() method (like a son is connected to father, so that son can make
use of father’s property). Idea is good, but how to do it
programmatically. Java say, use "extends" keyword and the problem is
solved.
The above two classes are modified as follows just with an addition of
extends keyword.
class Bird
{
public void walk()
{
System.out.println("Bird can walk");
}
}
The disjoint two classes are joined with extends keyword. That is,
"extends" joins or links two classes in Java. The advantage of linking is
now the Ostrich can make use of Bird’s methods. This is discussed down.
Bird b1 = Bird();
b1.walk();
Nothing great in the above code, as Bird object b1 is calling its own
walk() method (like you are eating from your own plate). Observe the
following code.
Ostrich object o1 is calling its own method run() and is no great. The
greatness comes now. Observe, the Ostrich object o1 is calling walk()
method of Bird (like you are eating from other’s place which is not
permitted by the other). Here object belongs to Ostrich and method
belongs to Bird. That is, walk() method of Bird is used by Ostrich. This
avoids writing again walk() method in Ostrich class (because Ostrich also
wants to walk). This we call as "code reusability".
b1.run();
The strange thing here is the Bird object is calling Ostrich method
run(). No it is not possible (like a father does not have right over
son’s property).
Inheritance
Now let us add some technical words (for nothing but to confuse you, but
no escape). When Ostrich extends Bird, there establishes a relation
between them (earlier not as they are disjoint). The relation we call as
"inheritance", one of the OOPs concepts, the other being encapsulation
and polymorphism. To inherit we used extends keyword. The class which
extends is known as subclass and the class which is getting extended is
known as super class. In the above code, Ostrich is subclass and Bird is
super class.
The rule says, "subclass can make use of super class members but super
class cannot make use of subclass members". That is, Bird cannot make use
of Ostrich methods.
Now, I am sure you are clear of what is inheritance, extends, super class
and subclass. Any query may be posted to me in the comment box down.
Note: Would you like to know a how super class can call subclass methods?
It is very secret. To know the secret click here (which is possible
through object casting that leads to polymorphism).
Now Ostrich also wants to eat but the eat() method is there in another
class Animal. Now, it is required to Ostrich to extend two classes Bird
and Animal. Observe the following pseudo code.
class Animal
{
// eat() method exists her
}
class Bird
{
// walk() method exists her
}
As you can observe in the above code, after extends two classes exist,
Bird and Animal. This is not permitted by Java. If you write multiple
classes after extends, it comes under multiple inheritance and Java does
not support. That is, Java permits to extend only one class. But Ostrich
wants both. How to solve the problem?
Very simple. As Java permits to extend only one class, we write multiple
classes that extends only one to the other like a ladder.
class Animal
{
// eat() method exists her
}
Let us rewrite the earlier Bird-Ostrich code where we add one more class
Animal.
class Animal
{
public void eat()
{
System.out.println("Animal can eat");
}
}
Types of Inheritance:::
There exists basically three types of inheritance.
Multilevel inheritance
Multiple inheritance
Hierarchical inheritance
1. In single inheritance, one class extends one class only. In multilevel
inheritance, the ladder of single inheritance increases.
2. In multiple inheritance, one class directly extends more than one
class.
3. In hierarchical inheritance one class is extended by more than one
class.
1. Multilevel Inheritance
class Aves
{
public void nature()
{
System.out.println("Generally, Aves fly");
}
}
class Bird extends Aves
{
public void eat()
{
System.out.println("Eats to live");
}
}
public class Parrot extends Bird
{
public void food()
{
System.out.println("Parrot eats seeds and fruits");
}
public static void main(String args[])
{
Parrot p1 = new Parrot();
p1.food(); // calling its own
p1.eat(); // calling super class Bird
method
p1.nature(); // calling super class Aves
method
}
}
Now, Parrot has two super classes Bird and Aves; but extended one-to-one.
Parrot can make use of the methods of Bird and Aves. Bird can make use of
the methods of Aves, but Parrot as a super class cannot access subclass
members. Following figure gives a schematic representation of the
multilevel hierarchy with the classes involved in the program.
Diagrammmmmmmmmmm
2. Multiple Inheritance
calss Aves { }
class Bird { }
public class Parrot extends Aves, Bird { }
In the above code, Parrot extends both Aves and Bird. This is not
supported by Java and the above code raises compilation error. Following
is the schematic representation.
Diagrammmmmmmmmmmm
3. Hierarchical Inheritance
class Aves
{
public void fly()
{
System.out.println("Generally, aves fly");
}
}
class Parrot extends Aves
{
public void eat()
{
System.out.println("Parrot eats fruits and seeds");
}
}
class Vulture extends Aves
{
public void vision()
{
System.out.println("Vulture can see from high altitudes");
}
}
public class FlyingCreatures
{
public static void main(String args[])
{ // all the
following code is composition for FlyingCreatures
Parrot p1 = new Parrot();
p1.eat(); // calling its
own member
p1.fly();
// calling super
class member by inheritance
Vulture v1 = new Vulture();
v1.vision(); // calling its own
member
v1.fly(); // calling super class member by
inheritance
}
}
In the above code, Aves class is extended by two classes – Parrot and
Vulture. Both classes can make use of the methods of Aves. Even though
the Parrot and Vulture are subclasses of the same class Aves, but still
they cannot make use of each other members. Parrot and Vulture are known
as "siblings". Siblings are disjoint and they cannot make use of other
members as between them no inheritance is involved (like two sons of a
father; one son's property cannot be shared by other but both can share
the property of father). Following is the schematic representation of the
classes involved.
Diagrammmmmmmm
Disadvantages of Inheritance
Method Overriding::
Subclass can make use of super class methods straight away by virtue of
inheritnace. If the subclass does not satisfy about the functionality
(output) of the super class method, the subclass can rewrite with its own
functionality with the same method name. This concept is known as "method
overriding", supported by OOP languages like C++/Java. In method
overriding, super class and subclass have the method with the same
signature – same parameters and same return type.
class Aves
{
public void nature()
{
System.out.println("Aves fly");
}
}
public class Vulture extends Aves
{
public void nature()
{
System.out.println("Flies very high altitudes");
}
public static void main(String args[])
{
Vulture v1 = new Vulture();
v1.nature();
}
}
In the above program, Aves and Vulture classes have the same method
nature() with their own functionalities (outputs).
If the super class and subclass have the same method, the subclass calls
its own method. By this rule, the subclass object, v1, calls its own
overridden method.
The method overloading and method overriding sounds similar; but they
differ completely.
Method Overloading Method Overriding
1. Happens in the same class Happens among two classes – a super class and
a subclass
2. No inheritance Happens in inheritance only
3. One method does not hide another Subclass method hides super class
method
4. Should have different parameters Should have same parameters
5. Return type is not bothered Should have the same return type
6. Leads to static binding and static polymorphism Leads to dynamic
binding, dynamic polymorphism and dynamic method dispatch
Table: Differences among overloading and overriding
class Test
{
public static void display()
{
System.out.println("Hello 1");
}
}
public class Demo extends Test
{
public static void display()
{
// super.display(); // raises compilation error
System.out.println("Hello 2");
}
public static void main(String args[])
{
display();
Test.display();
}
}
The display() method is static in the super class Test and also in
subclass Demo. Compiler does not treat it as method overriding as it
feels each display() method belong to it's own class.
// super.display();
"super" cannot be used with static members and raises compilation error.
display();
Test.display();
The display() declared in Demo class calls its own and Test.display()
calls Test class display() method. No ambiguity in understanding by the
compiler.
class Bird
{
public void eat()
{
System.out.println("Eats insects.");
}
}
public class Sparrow extends Bird
{
public void eat()
{
super.eat();
System.out.println("Eats grains.");
super.eat(); // again you can call
}
public static void main(String args[])
{
Sparrow s1 = new Sparrow();
s1.eat();
}
}
The eat() method exists in both Bird and Sparrow classes. We say, super
class method is overridden by subclass. s1.eat() calls its own (Sparrow)
method. Sparrow uses "super.eat();" to call Bird's eat() method. The next
program illustrates "static" with variables.
Note:
You have seen earlier "super" with methods. Let us go for with variables.
class Packing
{
int cost = 50;
}
public class TotalCost extends Packing
{
int cost = 100;
public void estimate()
{
System.out.println("Cost of articles Rs." + cost);
System.out.println("Packing expenses Rs." + super.cost);
System.out.println("Total to pay Rs." + (cost + super.cost));
}
public static void main(String args[])
{
TotalCost tc1 = new TotalCost();
tc1.estimate();
}
}
public Demo()
Constructor Overloading
In the code, creating object p3, the III constructor is accessed. From
III, with "this(100)" statement, the II constructor is accessed. Again
from II, the I is accessed without the statement "this()". As per the
parameter supplied to this(), the appropriate or corresponding
constructor is accessed.
Rules of using this()
What can:
Constructors are not inherited; only members (variables and methods) are
inherited. So declaring a constructor final does not have any meaning as
constructors cannot be overridden.
The methods which cannot be executed by JVM alone and depends on the
underlying OS are known as native methods. Native methods execution is
slow and for this reason many native methods throw a checked exception.
"const" keyword of C/C++ is not supported by Java and in its place, Java
uses "final" keyword. That is, a final variable cannot be reassigned.
Once assigned, cannot be modified later.
In the above code, the variable cost is declared as non-final and packing
as final. The cost variable is reassigned to 500 but packing cannot be(if
the comments are removed in the code, it is compilation error). After
comfortable with final variables let us go to final methods.
2. final Keyword with Methods
Now the super class would like to place a small restriction on subclass;
it says, few methods of it's cannot be overridden. The super class
declares those methods as final. That is, final methods of the super
class cannot be overridden.
class Bird
{
public final void eat() // final method, cannot be
overridden
{
System.out.println("Birds eat");
}
public void fly() // non-final method, can be
overridden
{
System.out.println("Birds fly");
}
}
public class Peacock extends Bird
{
public void fly()
{
System.out.println("Peacock flies small distances");
}
public static void main(String args[])
{
Peacock p1 = new Peacock();
p1.eat(); // calling super class final method
p1.fly(); // calling its own overridden
method
}
}
Abstract Classes::
You have seen earlier two access modifiers – static and final. Now let us
go for another modifier "abstract". "abstract" modifier can be applied to
methods and classes, but not with variables. "abstract" means no code or
no implementation and just declares the method without the code.
To achieve this, super class just declares its method without giving the
body. As compiler does not accept the method without body, to satisfy the
compiler, we declare the method as "abstract". That is, abstract method
does not have body (no implementation). If the super class declares the
method as abstract, subclass should and must override; else it is a
compilation error. This is how a super class imposes a restriction on the
subclass to forcibly override its method.
The compiler does not allow the super class to create an object as the
class contains some methods without body. To satisfy the compiler,
declare the class abstract. Declaring the class abstract, is a promise to
the compiler that the programmer is not going to create an object of it.
That is, with abstract classes, objects cannot be created.
Super class gives the names and these names are used by the subclass with
its choicest code. Let us make some rules as per the understanding of the
program.
In the earlier Gandhiji program all methods are abstract (includes two
methods). All the methods are implemented with body by subclass,
GreatPeople. If the programmer would like the subclass to give coding for
all the methods, he declares all the methods as abstract.
MotorCar includes two abstract methods and one concrete class. The
abstract methods, as per rule, are overridden by the subclass Car and the
concrete method, airConditioning(), is used as it is. The concrete method
is left to the discretion of the subclass to override or not.
interface Suzuki
{
public abstract void body();
}
interface Ford
{
public abstract void engine();
}
public class MotorCar implements Suzuki, Ford
{
public void body()
{
System.out.println("Fit Suzuki body");
}
public void engine()
{
System.out.println("Fit Ford engine");
}
public static void main(String args[])
{
MotorCar mc1 = new MotorCar();
mc1.body();
mc1.engine();
}
}
In the above code there are two interfaces – Suzuki and Ford. Both are
implemented by MotorCar because it would like to have the features of
both interfaces. For this reason (to have the functionality of many
classes) only, Java supports multiple inheritance through interfaces.
Just to inform there are multiple interfaces and not classes, tell the
compiler by replacing "extends" with "implements". MotorCar, after
implementing both the interfaces, overrides the abstract methods of the
both – body() and engine(); else program does not compile. Java supports
multiple inheritance partially through interfaces. Following figure gives
the view of the above interfaces.
Diagrammmmmmmm
Features of Interfaces
Defining an Interface
We know earlier, interface should have only abstract methods (without any
body or implementation code). The abstract methods give a template
structure of methods from which subclasses can be developed easily.
Subclass job is just to override (or give the code) as per its
convenience and need not think about the design part (how many methods it
should contain, what are they, how they are related etc). Interfaces play
a vital role in Java coding and designing modules.
Now Ostrich also wants to eat but the eat() method is there in another
class Animal. Now, it is required to Ostrich to extend two classes Bird
and Animal. Observe the following pseudo code.
class Animal
{
// eat() method exists her
}
class Bird
{
// walk() method exists her
}
As you can observe in the above code, after extends two classes exist,
Bird and Animal. This is not permitted by Java. If you write multiple
classes after extends, it comes under multiple inheritance and Java does
not support. That is, Java permits to extend only one class. But Ostrich
wants both. How to solve the problem?
Very simple. As Java permits to extend only one class, we write multiple
classes that extends only one to the other like a ladder.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Animal
{
// eat() method exists her
}
Let us rewrite the earlier Bird-Ostrich code where we add one more class
Animal.
class Animal
{
public void eat()
{
System.out.println("Animal can eat");
}
}
Java supports both specifiers and modifiers that can dictate the access.
An access specifier can be applied to any identifier like variables,
methods and classes but modifiers cannot be applied to every identifier,
there are limitations. For example, the modifiers applied to variables
cannot be used with classes and similarly with methods also. A full
discussion of specifiers is given later.
Following list gives the details of access specifiers and modifiers that
can be applied to classes, variables and methods.
Three modifiers exist that can be applied to classes. Modifier comes just
before the class name.
"The subclass overridden method cannot have weaker access than super
class method".
class Test
{
protected void display() // protected specifier
{
System.out.println("Hello 1");
}
}
public class Demo extends Test
{
void display() // overridden with default specifier
{
System.out.println("Hello 2");
}
public static void main(String args[])
{
new Demo().display();
}
}
We know access specifiers specify the access and access modifiers modify
the access of variables, methods and classes. In general, an access
modifier works between the classes of the same application or within the
classes of same package.
To understand better, let us take the examples of static and final access
modifiers. Generally a method or variable is called with an object, but
declaring static, you do not require the object. Similarly is with final
modifier also. Declaring a method final, the subclass is not allowed to
override the super method and a final variable cannot be reassigned.
Synchronized gives a meaning of multiple threads cannot access the same
method at a time. Now, you understand the meaning of "modifying the
access".
1. native Modifier
1
2
3
public static native void sleep(long) throws InterruptedException; //
belonging to Thread class
Observe native keyword in the above two statements. The functions' code
is written in other language (means, not in Java). To execute these
methods, Java takes the help of underlying OS.
2. volatile Modifier
Volatile variables are not optimized (to minimize execution time) for
performance by the compiler as their values are expected to get changed
at any time without information. Volatile is better used with multiple
threads that can change a variable value often.
3. transient Modifier
4. strictfp Modifier
Following table gives the list of access specifiers and modifiers that
can be applied to variables, methods and classes.
specifier/modifier local variable instance variable method
class
public NA A A A
protected NA A A NA
default A A A A
private NA A A NA
final A A A A
static NA A A NA
synchronized NA NA A NA
native NA NA A NA
volatile NA A NA NA
transient NA A NA NA
strictfp NA NA A A
A: Allowed NA: Not Allowed
private variables and methods of a class can be accessed within the same
class only. By inheritance, even subclasses cannot use by composition.
Maximum other classes should call through the public methods of the same
class as in the following program.
class Test
{
private int x = 10;
public void display()
{
System.out.println(x);
}
}
public class Demo extends Test
{
public static void main(String args[])
{
Demo d1 = new Demo();
// System.out.println(d1.x); // error (inheritance)
Demo can use Test class object to call display() method to print x value.
Dynamic Polymorphism::
class Bird
{
public void eat() // I
{
System.out.println("All birds eat");
}
}
class Peacock extends Bird
{
public void eat() // II
{
System.out.println("Peacock eats grains");
}
}
class Vulture extends Bird
{
public void eat() // III
{
System.out.println("Vulture eats flesh");
}
}
class Crane extends Bird
{
public void eat() // IV
{
System.out.println("Crane eats fish");
}
}
public class DynamicPolyDemo
{
public static void main(String args[])
{
Bird b1 = new Bird(); b1.eat(); // calls I
Peacock p1 = new Peacock(); b1 = p1; b1.eat(); // calls II
Vulture v1 = new Vulture(); b1 = v1; b1.eat(); // calls III
Crane c1 = new Crane(); b1 = c1; b1.eat(); // calls IV
}
}
Subclasses Peacock, Vulture and Crane overrides the eat() method of Bird.
b1 = p1;
b1.eat();
In the above statement, subclass Peacock object p1 is assigned to super
class Bird object b1. Earlier, in Object Casting, we know if a subclass
object is assigned to a super class object, the super class object will
call subclass overridden method. As per this rule, b1 will call p1 eat()
method. Infact, the b1 contains the reference of p1.
b1 = v1;
b1.eat();
Now, the Bird object b1 is assigned with the subclass Vulture object v1.
Now the earlier p1 reference is replaced by v1. Now b1 points to v1
location. Now b1 calls v1 eat method.
b1 = c1;
b1.eat();
Again, the v1 reference in the super class object b1 is replaced by Crane
object c1. Now, b1 calls Crane's eat() method.
Observe the code, the statement b1.eat() prints 4 different outputs by
calling 4 different eat() methods. The same method when called different
times giving different values is known a polymorphism ("poly" means many
and "morphism" means forms).
Interface Polymorphism
The same Bird program, in the earlier example, can be modified to suit
with interfaces. Now declare Bird as an interface. We know that reference
variables can be created with abstract classes and interfaces (but not
objects). Read the following program.
interface Bird
{
public abstract void eat(); // I
}
class Peacock implements Bird
{
public void eat() // II
{
System.out.println("Peacock eats grains");
}
}
class Vulture implements Bird
{
public void eat() // III
{
System.out.println("Vulture eats flesh");
}
}
class Crane implements Bird
{
public void eat() // IV
{
System.out.println("Crane eats fish");
}
}
public class DynamicPolyDemo
{
public static void main(String args[])
{
Bird b1; // reference variable of interface
Peacock p1 = new Peacock(); b1 = p1; b1.eat(); // calls II
Vulture v1 = new Vulture(); b1 = v1; b1.eat(); // calls III
Crane c1 = new Crane(); b1 = c1; b1.eat(); // calls IV
}
}
Here Bird is interface and not a concrete class (in the earlier program
it is concrete class).
Bird b1;
b1 is reference variable and not object.
b1 = p1;
b1.eat();
Subclass Peacock object is assigned to the reference variable b1 of
interface Bird. Here, super class is an interface and eat() is an
abstract method. When a subclass object is assigned to a super class
reference variable, the reference variable calls subclass overridden
method. Now, b1 calls subclass Peacock's eat() method.
The addresses of subclass objects, p1, v1 and c1, in the super class
reference variable b1 are replaced in every statement dynamically at
runtime. Every time when b1.eat() method is called, it prints different
outputs. This is known as polymorphism. Because polymorphism is achieved
at runtime dynamically, this is known as dynamic polymorphism. Here,
dynamic polymorphism is achieved through interfaces.
Java novices are not much aware of static to non-static calling. Let us
find the rules through a program.
In the following code, show() method is non-static and display() is
static. The question is "Can we call a non-static method from static
method?". Everyone says simply "no" because it requires an object to
call. Anyhow, let us observe the compiler message.