0% found this document useful (0 votes)
28 views23 pages

OOPS With Java-Module 3

Uploaded by

meenakshiic78
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
28 views23 pages

OOPS With Java-Module 3

Uploaded by

meenakshiic78
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 23

OOPS With JAVA

Module -3

Chapter -1 Inheritance
Inheritance: Acquiring properties from one class (Parent class) into another class (child class)
is called Inheritance.
 Parent class is also called as Super class or Base class and Child class is
also called as Sub class or Derived class.

The Acquiring properties from Parent class to child class are:


 Instance variables of Super class can be accessible inside subclass
 Methods of super class can be accessible inside sub class.
 Inheritance represents the IS-A relationship which is also known as a parent child relationship.
Advantages of Inheritance:
Code reusability
Duplicate code is eliminated

The syntax of Java Inheritance


class Subclass-name extends Superclass-name {
}
The extends keyword indicates that you are making a new class that derives from an existing
class. The meaning of "extends" is to increase the functionality.

1.1 Types of Inheritance


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();
}
}
Output:
barking...
eating...

Multilevel Inheritance: When there is a chain of inheritance, it is known as multilevel


inheritance. As you can see 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();
}
}

Output:
weeping...
barking...
eating...

Hierarchical Inheritance : When two or more classes inherits a single class, it is known
as hierarchical inheritance. In the example given below, Dog and Cat classes inherits 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
}
}
Output:
meowing...
eating...

1.2 Inheritance Basics


To inherit a class, you simply incorporate the definition of one class into another by
using the extends keyword.

// A simple example of inheritance.


// 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();
}
}
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 general form of a class declaration that


inherits:

class subclass-name extends superclass-name {


// body of class
}
1.3 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. For example, consider the
following simple class hierarchy:

/* This program contains an error and will not


compile.
*/

// Create a superclass.
class A {
int i; // default access
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);
}
}

1.4 A More Practical Example

Here, the final version of the Box class developed in the preceding chapter will be extended to
include a fourth component called weight. Thus, the new class will contain a box’s width,
height, depth, and weight.
// This program uses inheritance to extend Box.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 used when no dimensions specified


Box() {
width = -1; // use -1 to indicate
height = -1; // an uninitialized
depth = -1; // box
}

// constructor used when cube is created


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

// compute and return volume


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

// 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);
System.out.println();

vol = mybox2.volume();
System.out.println("Volume of mybox2 is " + vol);
System.out.println("Weight of mybox2 is " + mybox2.weight);
}
}
Output:
Volume of mybox1 is 3000.0
Weight of mybox1 is 34.3

Volume of mybox2 is 24.0


Weight of mybox2 is 0.076

2. Using super

 In Java, the super keyword is used to refer to the immediate parent class object.
 super has two general forms.
 The first calls the superclass’ constructor.
 The second is used to access a member of the superclass that has been hidden by a member
of a subclass.

2.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.
// A complete implementation of BoxWeight.
class Box {
private double width;
private double height;
private 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 used when no dimensions specified


Box() {
width = -1; // use -1 to indicate
height = -1; // an uninitialized
depth = -1; // box
}

// constructor used when cube is created


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

// compute and return volume


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

// BoxWeight now fully implements all constructors.


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); // call superclass constructor


weight = m;
}

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

// constructor used when cube is created


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

class DemoSuper {
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:
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
2.2 A Second Use for super
The second form of super, it always refers to the superclass of the subclass 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.


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) {
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:

i in superclass: 1
i in subclass: 2
3. Creating a Multilevel Hierarchy
Given three classes called A, B, and C, C can be a subclass of B, which is a subclass of A. In this case, C
inherits all aspects of B and A. To see how a multilevel hierarchy can be useful, consider the following program.

In it, 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.

// Extend BoxWeight to include shipping costs.

// Start with Box.


class Box {
private double width;
private double height;
private 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 used when no dimensions specified


Box() {
width = -1; // use -1 to indicate
height = -1; // an uninitialized
depth = -1; // box
}

// constructor used when cube is created


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

// compute and return volume


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

// Add 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); // call superclass constructor
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) { // pass object to constructor
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); // call superclass constructor
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 shipment1 is " + vol);
System.out.println("Weight of shipment1 is "
+ shipment1.weight);
System.out.println("Shipping cost: $" + shipment1.cost);
System.out.println();

vol = shipment2.volume();
System.out.println("Volume of shipment2 is " + vol);
System.out.println("Weight of shipment2 is "
+ shipment2.weight);
System.out.println("Shipping cost: $" + shipment2.cost);
}
}
Output:
Volume of shipment1 is 3000.0
Weight of shipment1 is 10.0
Shipping cost: $3.41

Volume of shipment2 is 24.0


Weight of shipment2 is 0.76
Shipping cost: $1.28

4. When Constructors Are Executed


A class hierarchy, constructors complete their execution in order of derivation, from superclass to subclass.
Further, 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 constructor of each superclass will be
executed.

// Demonstrate when constructors are executed.

// Create a super class.


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:
Inside A's constructor
Inside B's constructor
Inside C's constructor

5. Method Overriding
Method overriding occurs when a subclass provides a specific implementation for a method that is
already defined in its superclass.
Conditions for Method Overriding:
Same method name
Same method type signature (parameters and return type)
Key Point:
The version of the method defined by the superclass is hidden when called through the subclass.
// 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 and j: " + i + " " + j);
}
}
// Create a subclass by extending class A.
class B extends A {
int k;

B(int a, int b, int c) {


super(a, b);
k = c;
}
// overload show()
void show(String msg) {
System.out.println(msg + k);
}
}
class Override {
public static void main(String[] args) {
B subOb = new B(1, 2, 3);

subOb.show("This is k: "); // this calls show() in B


subOb.show(); // this calls show() in A
}
}

Output:
This is k: 3
i and j: 1 2

6. Dynamic Method Dispatch


 Method overriding in Java forms the foundation for dynamic method dispatch.
 Dynamic method dispatch is the mechanism by which a call to an overridden method is
resolved at run time, rather than compile time.
 Dynamic method dispatch is crucial for achieving run-time polymorphism in Java.
 A superclass reference variable can refer to a subclass object.
 When an overridden method is called through a superclass reference, Java determines the
version to execute based on the type of the object being referred to at run time.
 It is the type of the object (not the type of the reference variable) that determines which
version of an overridden method will be executed.
 Different versions of an overridden method are called when different types of objects are
referred to through a superclass reference variable.

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

Inside A's callme method


Inside B's callme method
Inside C's callme method

6.1 Applying Method Overriding



 The following 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.
// 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 for Figure is undefined.");return 0;
}
}

class Rectangle extends Figure {


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

// override area for rectangledouble


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

class Triangle extends Figure {


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

// override area for right triangle


double area() {
System.out.println("Inside Area for 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:
Inside Area for Rectangle.
Area is 45
Inside Area for Triangle.
Area is 40
Area for Figure is undefined.
Area is 0
7. Using Abstract Classes

 Java abstract class is a class that can not be initiated by itself, it needs to be subclasses by
another class to use its properties.

 An abstract class is declared using the “abstract” keyword in its class definition.

 The main purpose of an abstract class is to provide a common structure for its subclasses,
ensuring that they implement certain essential methods.

 An abstract class can also have constructors, data members, and static methods

 To declare an abstract method, use this general form:


abstract type name(parameter-list);

// 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("Inside Area for Rectangle.");
return dim1 * dim2;
}
}

class Triangle extends Figure {


Triangle(double a, double b) {
super(a, b);
}
// override area for right triangle
double area() {
System.out.println("Inside Area for Triangle.");
return dim1 * dim2 / 2;
}
}
class AbstractAreas {
public static void main(String[] args) {
// Figure f = 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:
Inside Area for Rectangle.
Area is 45
Inside Area for Triangle.
Area is 40

8. Using final with Inheritance


The keyword final has two uses. The uses of final are described below.

a. Using final to Prevent Overriding


While method overriding is one of Java’s most powerful features, there will be times when
you will want to prevent it from occurring. To disallow a method from being overridden,
specify final as a modifier at the start of its declaration. Methods declared as final cannot
be overridden.

class A {
final void meth() {
System.out.println("This is a final method.");
}
}

class B extends A {
void meth() { // ERROR! Can't override.
System.out.println("Illegal!");
}
}

 Because meth( ) is declared as final, it cannot be overridden in B. If you


attempt to do so, a compile-time error will result.
 Methods declared as final can sometimes provide a performance enhancement:
The compiler is free to inline calls to them because it “knows” they will not be
overridden by a subclass.

b. Using final to Prevent Inheritance


Sometimes you will want to prevent 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 as final, too. As you
might expect, itis illegal to declare a class as both abstract and final since an abstract class is incomplete by
itself and reliesupon its subclasses to provide complete implementations.
final class A {
//...
}

// The following class is illegal.


class B extends A { // ERROR! Can't subclass A
//...}

9. Local Variable Type Inference and Inheritance


 Local variable type inference to the Java language, which is supported by the context-sensitive
keyword var. It is important to have a clear understanding of how type inference works within an
inheritance hierarchy. 

 However, it is critical to remember that, when using local variable type inference, the inferred type
of a variable is based on the declared type of its initializer.
 Therefore, if the initializer is of the superclass type, that will be the inferred type of the variable.
 It does not matter if the actual object being referred to by the initializer is an instance of a derived
class. For example, consider this program:

class MyClass {
// ...
}

class FirstDerivedClass extends MyClass {


int x;
// ...
}

class SecondDerivedClass extends FirstDerivedClass {


int y;
// ...
}

class TypeInferenceAndInheritance {
// Return some type of MyClass object.
static MyClass getObj(int which) {
switch(which) {
case 0: return new MyClass();
case 1: return new FirstDerivedClass();
default: return new SecondDerivedClass();
}
}

public static void main(String[] args) {


// Here, getObj() returns a MyClass object.
var mc = getObj(0);

// In this case, a FirstDerivedClass object is returned.


var mc2 = getObj(1);

// Here, a SecondDerivedClass object is returned.


var mc3 = getObj(2);

//mc2.x = 10; // Wrong! MyClass does not have an x field.


//mc3.y = 10; // Wrong! MyClass does not have a y field.
}
}

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

Object defines the following methods, which means that they are available in every object.

Method Purpose
Object clone( ) Creates a new object that is the same as the object being
cloned.
boolean equals(Object object) Determines whether one object is equal to another.
void finalize( ) Called before an unused object is recycled. (Deprecated
by JDK 9.)
Class<?> getClass( ) Obtains the class of an object at run time.
int hashCode( ) Returns the hash code associated with the invoking
object.
void notify( ) Resumes execution of a thread waiting on the invoking
object.
void notifyAll( ) Resumes execution of all threads waiting on the invoking
object.
String toString( ) Returns a string that describes the object.
void wait( ) Waits on another thread of execution.
void wait(long milliseconds) void
wait(long milliseconds,
int nanoseconds)

You might also like