JAVA-Module-3-Chapter1 JITD
JAVA-Module-3-Chapter1 JITD
MODULE-III
CHAPTER 1
Inheritance
Inheritance is one of the cornerstones of object-oriented programming because it 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 then be inherited by other, more specific classes, each adding those things that are
unique to it.
It is the mechanism in java by which one class is allow to inherit the features (instance
variables and methods) of another class.
2.1.2 Advantages
1. Code Reusability: Inheritance in Java allows for code reuse, saving you ample time and effort
during software development. Sub-class can reuse some of the needed code of the superclass while
inheriting methods and properties.
3. Class Hierarchy: In Java, inheritance enables you to create a class hierarchy, which is useful for
modelling real-world objects and establishing their relationships.
4. Code Maintainability: With Java inheritance, it is easier to maintain code as developers need to
make changes only in the single location inherited by the child class.
5. Code Modularity: Inheritance divides code into parent and child classes, which helps to write
more organised and modular code.
6. Abstraction: Inheritance in Java enables you to create abstract classes defining a common
interface for a group of related classes. Hence, promoting abstraction and encapsulation, which
makes it easier to maintain and extend code.
7. Code Flexibility: Sub-class can add their methods and fields along with the features inherited
from the superclass, which allows code flexibility.
ii. Multilevel Inheritance: In Multilevel Inheritance, a derived class will be inheriting a base class
and as well as the derived class also act as the base class to other class. In below image, the class A
serves as a base class for the derived class B, which in turn serves as a base class for the derived
class C.
iii. Hierarchical Inheritance: In Hierarchical Inheritance, one class serves as a superclass (base
class) for more than one sub class. In below image, the class A serves as a base class for the derived
class B,C and D.
Multiple Inheritance and Hybrid inheritance: Please note that Java does not support multiple
inheritance and hybrid inheritance with classes. In java, we can achieve these inheritances only
through Interfaces.
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: "); Output:
superOb.showij(); Contents of superOb:
subOb.i = 7; i and j: 10 20
subOb.j = 8; Contents of subOb:
subOb.k = 9; i and j: 7 8 k: 9
System.out.println("Contents of subOb: "); Sum of i, j and k in subOb:
subOb.showij(); i+j+k: 24
subOb.showk();
System.out.println("Sum of i, j and k in subOb:");
subOb.sum();
}
}
As you can see, the subclass B includes all of the members of its superclass, A.
This is why subOb can access i and j and call showij( ).
Also, 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 also a completely independent, stand-alone class.
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.
A 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.
Once you have created a superclass 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.
Here, weightbox is a reference to BoxWeight objects, and plainbox is a reference to Box objects.
Since BoxWeight is a subclass of Box, it is permissible to assign plainbox a reference to the
weightbox object.
It is important to understand that it is the type of the reference variable—not the type of the
object that it refers to—that determines what members can be accessed.
That is, when a reference to a subclass object is assigned to a superclass reference variable, you
will have access only to those parts of the object defined by the superclass.
This is why plainbox can’t access weight even when it refers to a BoxWeight object.
If you think about it, this makes sense, because the superclass has no knowledge of what a
subclass adds to it.
This is why the last line of code in the preceding fragment is commented out.
It is not possible for a Box reference to access the weight field, because Box does not define one.
Here, BoxWeight( ) calls super( ) with the arguments w, h, and d. This causes the Box( )
constructor to be called, which initializes width, height, and depth using these values.
BoxWeight no longer initializes these values itself.
It only needs to initialize the value unique to it: weight. This leaves Box free to make these
values private if desired.
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 arguments.
For example, here is a complete implementation of BoxWeight that provides constructors for the
various ways that a box can be constructed.
In each case, super( ) is called using the appropriate arguments.
Notice that width, height, and depth have been made private within Box.
When a subclass calls super( ), it is calling the constructor of its immediate superclass.
Thus, super( ) always refers to the superclass immediately above the calling class.
This is true even in a multileveled hierarchy.
Also, super( ) must always be the first statement executed inside a subclass constructor.
2. Super can be used to refer immediate parent class instance variables and methods
Super acts somewhat like this, except that it always refers to the superclass of the sub class in
which it is used. This usage has the following general form:
super.member
Here, member can be either a method or an instance variable.
This form of super is most applicable to situations in which member names of a subclass hide
members by the same name in the superclass.
Consider this simple class hierarchy:
// 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 the i in A
B(int a, int b) { Output:
super.i = a; // i in A i in superclass: 1
i in subclass: 2
i = b; // i in B
}
void show() {
System.out.println("i in superclass: " + super.i);
System.out.println("i in subclass: " + i);
}
}
Consider the following program. In this program, the subclass BoxWeight is used as a superclass
to create the subclass called Shipment.
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.
Because of inheritance, Shipment can make use of the previously defined classes of Box and
BoxWeight, adding only the extra information it needs for its own, specific application.
This is part of the value of inheritance; it allows the reuse of code.
This example illustrates one other important point: super( ) always refers to the constructor in
the closest superclass.
The super( ) in Shipment calls the constructor in BoxWeight.
The super( ) in BoxWeight calls the constructor in Box.
In a class hierarchy, if a superclass constructor requires parameters, then all subclasses must pass
those parameters “up the line.” This is true whether or not a subclass needs parameters of its
own.
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 you wish to access
the superclass version of an overridden method, you can do so by using super.
Method overriding occurs only when the names and the type signatures of the two methods are
identical. If they are not, then the two methods are simply overloaded. Example for overloading.
The version of show( ) in B takes a string parameter. This makes its type signature different from
the one in A, which takes no parameters. Therefore, no overriding (or name hiding) takes place.
Instead, the version of show( ) in B simply overloads the version of show( ) in A.
7. Static binding is being used for Dynamic binding is being used for
overloaded methods. overriding methods.
10. The argument list should be The argument list should be the same in
different while doing method method overriding.
overloading.
This program creates one superclass called A and two subclasses of it, called 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.
As the comment inside main( ) indicates, it is no longer possible to declare objects of type
Figure, since it is now abstract.
And, all subclasses of Figure must override area( ).
To prove this to yourself, try creating a subclass that does not override area( ).
You will receive a compile-time error.
Although it is not possible to create an object of type Figure, you can create a reference variable
of type Figure.
The variable figref is declared as a reference to Figure, which means that it can be used to refer
to an object of any class derived from Figure.
As explained, it is through superclass reference variables that overridden methods are resolved at
run time.
In the program, a hierarchy is created that consists of three classes, at the top of which is
MyClass.
FirstDerivedClass is a subclass of MyClass, and SecondDerivedClass is a subclass of
FirstDerivedClass.
The program then uses type inference to create three variables, called mc, mc2, and mc3 by
calling getObj( ).
The getObj( ) method has a return type of MyClass (the superclass), but returns objects of type
MyClass, FirstDerivedClass, or SecondDerivedClass, depending on the argument that it is
passed.
As the output shows, the inferred type is determined by the return type of getObj( ), not by the
actual type of the object obtained.
Thus, all three variables will be of type MyClass.
The methods getClass( ), notify( ), notifyAll( ), and wait( ) are declared as final.
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 toString( ) method returns a string that contains a description of the object on which it is
called.