8 Inheritance in Java

8.1 INTRODUCTION

The term inheritance implies that one class can inherit a part or all of its structure and behaviour from another class. Inheritance provides the idea of reusability, i.e., a code once written can be used again and again in a number of new classes. The class that does the inheriting is called a subclass of the class from which it inherits. If class B is a subclass of class A , it can also be said that class A is a super class of class B . (Sometimes the terms derived class and base class are used instead of subclass and super class) (Figure 8.1). A subclass can add to the structure and behaviour that it inherits. It can also replace or modfy inherited behaviour (though not inherited structure). The relationship between a subclass and a super class can be shown in a diagram with the subclass below, and connected to, its super class .

images

Figure 8.1 Implementation of inheritance

In Java, when a new class is created, it can be declared that it is a subclass of an existing class. In order to define a class B as a subclass of a class A, it should be written as follows:

class B extends A
{
   //functions and fields;
}

8.2 TYPES OF INHERITANCE

Inheritance is generally of five types (Figure 8.2): single level, multilevel, multiple, hierarchical and hybrid.

The syntax of deriving a new class from an already existing class is shown as follows:

class new_class_name extends mode old_class_name
{
};

Where class is the keyword used to create a class. new_class_name is the name of new derived class. old_class_name is the name of an already existing class. It may be a user-defined or a build-in class. The extend keyword is used for inheriting the class.

images

Figure 8.2 Different types of inheritance

8.2.1 Single-level Inheritance

In single level inheritance, there is just one base and one derived class. It is represented as follows:

In Java code, this can be written as follows:

images

8.2.2 Multilevel Inheritance

In multilevel inheritance, there is one base class and one derived class at the same time at one level. At the next level, the derived class becomes base class for the next derived class and so on. This is shown as:

images

The class A and class B together form one level, class B and class C together form another level and so on. For class B, class A is the parent and for class C, class B is the parent; thus in this inheritance level, A can be called the grandparent of class C, and class C the grandchild of class A.

8.2.3 Multiple Inheritance

In a multiple inheritance, a child can have more than one parent, i.e., a child can inherit properties from more than one class. Diagrammatically, this is as shown below:

images

Unfortunately, Java does not support the multiple inheritances through classes though it supports using interfaces which is discussed in the next chapter. That is, in Java one cannot write the following syntax:

class A { } class B {} class C extends A extends B

8.2.4 Hierarchical Inheritance

In this type of inheritance, multiple classes share the same base class. That is, numbers of classes inherit the properties of one common base class. The derived classes may also become base classes for other classes. This is shown in Figure 8.3 .

images

Figure 8.3 The hierarchical inheritance

For example, a university has a number of colleges under its affiliation. Each college may use the university name, the name of its chairperson, its address, phone number, etc.

Similarly, a vehicle possesses a number of properties or features and the common properties of all the vehicles may be put under one class vehicle, and different classes like two-wheeler, four-wheeler and three-wheeler can inherit the vehicle class.

As another example, in an engineering college, various departments can be termed as various classes which may have one parent common class-the name of the engineering college. Again for each department, there may be various classes, like lab staff, faculty class, etc. In Java code, the first level can be seen as follows:

class A
{
}
class B extends A    class C extends A     class D extends A
{}                   {}                    {}

8.2.5 Hybrid Inheritance

Consider Figure 8.4 as shown below.

images

Figure 8.4 Implementation of hybrid inheritance

For the first half of the figure, the hierarchical inheritance is shown by breaking the figure:

images

The second half of the figure shows multiple inheritance:

images

The second figure for hybrid inheritance may be viewed as shown below:

images

As said earlier, Java does not support multiple inheritance through classes, so code for the above will be given while working with interfaces.

8.3 PROGRAMMING EXAMPLES

/*PROG 8.1 DEMO OF SINGLE LEVEL INHERITANCE VER 1 */
class A
{
   void show_A()
   {
      System.out.println("
	DEMO OF SINGLE LEVEL
                               INHERITANCE");
   System.out.println("
*+*+*+*+*+*+*+*+*+*+*+*+*+*
");
      System.out.println("
	HELLO FROM CLASS A");
   System.out.println("
*+*+*+*+*+*+*+*+*+*+*+*+*+*
");
   }
}
class B extends A
{
};
class JPS1
{
   public static void main(String args[])
   {
         B obj = new B();
         obj.show_A();
   }
}
OUTPUT:

   DEMO OF SINGLE LEVEL INHERITANCE
+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*
          HELLO FROM CLASS A
+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*

Explanation: For class A a single function show_A is declared. The line class B extends A tells the compiler that B is a new class and class A is inherited in class B. This makes class A the parent of class B, where class A and B are also known as the base class and derived class, respectively. In class B, any data or function has not been defined; therefore, it contains only inherited members from class A. In the main function, an object of class B is created and the function show_A() is called, which was inherited from class A.

/*PROG 8.2 DEMO OF SINGLE LEVEL INHERITANCE VER 2 */
import java.io.*;
import java.util.*;
class base
{
   private int sup_a;
   public void input1(int x)
   {
         sup_a = x;
   }
   public void show1()
   {
         System.out.println("
 Value of sub_a");
         System.out.println("*********************");
         System.out.println("
sup_a:=" + sup_a);
         System.out.println("*********************");
   }
};
class derived extends base
{
   private int sub_a;
   public void input2(int x)
   {
         sub_a = x;
   }
   public void show2()
   {
         System.out.println("
 Value of sub_b");
         System.out.println("*********************");
         System.out.println("sub_a:=" + sub_a);
         System.out.println("*********************");
   }
}
class JPS2
{
   public static void main(String args[])
   {
         derived obj = new derived();
         obj.input1(200);
         obj.input2(400);
         obj.show1();
         obj.show2();
   }
}2

OUTPUT:

 Value of sub_a
*********************
sup_a:=200
*********************
Value of sub_b
*********************
sub_a:=400
*********************

Explanation: In the program in base class, there is one private data member sub_a and two functions for input and show. After inheriting class base in class derived, the class derived has a total of four public member functions: two of its own and two inherited from class base. The class derived also has one private data member sub_a. In the main function, all four functions are called by an object of derived class.

/* PROG 8.3 ACCESSING PRIVATE VARIABLE */
class A
{
   private int num_A;
   void input_A(int x)
   {
          num_A = x;
   }
   int getnum()
   {
          return num_A;
   }
}
class B extends A
{
   private int num_B;
   void input_B(int x)
   {
          num_B = x;
   }
   void show()
   {
      System.out.println(" num_A := " + getnum());
      System.out.println(" num_B := " + num_B);
   }
};
class JPS5
{
   public static void main(String[] args)
   {
          B obj = new B();
          System.out.println("Value of num_A and num_B is ");
          obj.input_A(100);
          obj.input_B(200);
          obj.show();
   }
}

OUTPUT:

Value of num_A and num_B is
num_A := 100
num_B := 200

Explanation: In earlier chapters, it was shown how to access a private data member of a class. The method was to simply define a public member function which returns the value of the private data member. The num in A is private; therefore, a public member function getnum is written which returns the value of num. The function getnum is called in the show method of class B. In the main function, all functions are called through an object of class B.

/*PROG 8.4 AREA AND VOLUME CALCULATION USING INHERITANCE */
import java.util.*;
import java.io.*;
class Area
{
   protected int length, width;
   public void input1()
   {
          Scanner sc = new Scanner(System.in);
          System.out.println("Enter the length and width");
          length = sc.nextInt();
          width = sc.nextInt();
   }
}
class Volume extends Area
{
   private int height;
   public void input2()
   {
          input1();
          Scanner sc = new Scanner(System.in);
          System.out.println("Enter the height");
          height = sc.nextInt();
   }
   void show()
   {
     System.out.println("Length      :="+length);
     System.out.println("Width       :="+width);
     System.out.println("Area        :="+length * width);
     System.out.println("Height      :="+height);
     System.out.println("Volume      :="+length*width* height);
   }
}
class JPS6
{
   public static void main(String args[])
   {
          Volume v = new Volume();
          v.input2();
          v.show();
   }
}

OUTPUT:

Enter the length and width
2
2

Enter the height
2

Length    := 2
Width     := 2
Area      := 4
Height    := 2
Volume    := 8

Explanation: In the class area, there are two protected data members: length and width. Function input1 takes input from keyboard into these data items directly. The class Volume inherits the class Area. The class Volume contains one data member: height. The class calculates area by using the inherited data members, length and width, and finds volume with the aid of height with length and width. Note that only the derived class function input2 is called inside the main function. This function in turn calls input1 of the Area class and takes input from the keyboard. The function show calculates the area and volume and displays the same.

/*PROG 8.5 CONCATENATING TWO STRING */
import java.io.*;
import java.util.*;
class first
{
   private String name;
   void input_f()
   {
          Scanner sc = new Scanner(System.in);
          System.out.println("Enter the name ");
          name = sc.next();
   }
   String getname()
   {
          return name;
   }
}
class second extends first
{
   private String sname;
   void input_s()
   {
          Scanner sc = new Scanner(System.in);
          System.out.println("Enter the name");
          sname = sc.next();
   }
   void show()
   {
          String con;
          con = getname() + " " + sname;
          System.out.println("name := " + getname());
          System.out.println("sname := " + sname);
          System.out.println("
************************");
          System.out.println("Joint name := " + con);
          System.out.println("**************************");
   }
}
class JPS7
{
   public static void main(String[] args)
   {
          second obj = new second();
          obj.input_f();
          obj.input_s();
          obj.show();
   }
}
OUTPUT:

Enter the name
HARI
Enter the name
PANDEY
name := HARI
sname := PANDEY
************************************
Joint name := HARI PANDEY
************************************

Explanation: The class first takes one string from the console and stores it in the private data member 'name'. To access this string name in the derived class 'second', a public member function getname is written in base class 'first'. In the main function, the class second first calls the input_f method which initializes the string name of class first. The method call input_s initializes the string sname of second class. In the show method of class second, the private data member 'name' is obtained by a call to getname method, and sname is concatenated with it.

/*PROG 8.6 BEHAVIOUR OF PROTECTED MEMBERS IN INHERITANCE */
class A
{
   protected int pa;
}
class B extends A
{
   protected int pb;
}
class JPS8

{
   public static void main(String[] args)
   {
          B obj = new B();
          obj.pa = 20;
          obj.pb = 30;
          System.out.println("pa = " + obj.pa);
          System.out.println("pb = " + obj.pb);
   }
}
OUTPUT:

pa = 20
pb = 30

Explanation: In Java, protected members can be accessed outside the class and are inherited to derived class also.

/*PROG 8.7 DEMO OF TWO LEVEL INHERITANCE */
class first
{
   public void show_f()
   {
          System.out.println("
Hello from first");
   }
}
class second extends first
{
   public void show_s()
   {
          System.out.println("
Hello from second");
   }
}
class third extends second
{
   public void show_t()
   {
          show_f();
          show_s();
          System.out.println("
Hello from third
");
   }
}
class JPS9
{
   public static void main(String[] args)
   {
          third t = new third();
          t.show_t();
   }
}

OUTPUT:

Hello from first
Hello from second
Hello from third

Explanation: The above program demonstrates two levels of inheritance. The class first is the base class (parent class) for class second (child class) and, class second is the base class (parent class) for class third (child class). In turn, class first is the grandfather of class third (grand child). In show_t function of class third, show_s is inherited directly from class second but show_f is inherited directly from class first through class second.

8.4 METHOD OVERRIDING

In method overriding, a base class method is overridden in the derived class. That is, the same method is written with the same signature as of the base class method but different implementation. Method overriding is often used in inheritance to override the base class implementation of the method and provide its own implementation. In method overloading, arguments and type of arguments are used to distinguish between two functions, but in method overriding no such distinction can be made. In method overriding, the signature of the two methods must match. This is shown in the program given below.

/*PROG 8.8 DEMO OF METHOD OVERRIDING */
class A{
   void show()
   {
   System.out.println("
Hello from A");
   }
}
class B extends A
{
   void show()
   {
          System.out.println("
Hello from B ");
   }
}
class JPS10
{
   public static void main(String args[])
   {
          B obj = new B();
          obj.show();
   }
}
OUTPUT:
Hello from B

Explanation: In the class B, the function show is overridden. The function show of class A is now hidden. From the main function, the statement obj.show, on execution, calls the show function of the class B.

8.5 DYNAMIC METHOD DISPATCH

Binding is the process of linking the function call with the place where function definition is actually written so that when a function call is made, it can be ascertained where the control has to be transferred. Binding is also called linking, and is of two types:

1.   Static binding

2.   Dynamic binding.

When at compile time, it is known which function will be called in response to a function call, the binding is said to be static binding, compile time binding or early binding. Static binding is called so because before the program executes, it is fixed that a particular function be called in response to a function call. Each time the program executes, the same function will be called. As the linking is done at compile time, early to the execution of the program, it is also known as compile time binding or early binding.

When it is not ascertained as to which function is to be called in response to a function call, binding is delayed till the program executes. At run time, the decision is taken as to which function is to be called in response to a function call. This type of binding is known as late binding, runtime binding or dynamic binding. Dynamic binding is purely based on finding the addresses of pointers, and as addresses are generated during run time or when the program executes, this type of binding is known as run time or execution time binding.

One type of polymorphism seen earlier is compile time polymorphism, which is of two types: function polymorphism/overloading and operator overloading.

Another type of polymorphism is the run time polymorphism, in which at run time, it is decided, which function is to be called by checking the pointer and its contents. It is necessary in situations, where there are two functions with the same name in both derived class and base class. At run time, it is decided using references and objects, as to which function of which class is to be called.

Dynamic method dispatch is the mechanism by which a call to an overridden function is resolved at run time, rather than at compile time. It is the mechanism through which Java implements run time polymorphism. Before understanding this, it is important to understand the concept of Java in inheritance:' A super class reference can refer to a derived class object'. For example consider the code:

class A { }
class B extends A{ }
B b = new A ();                 is perfectly valid

In this code, the reference is of B class but it is referring to a derived class object. Note that the reverse is not true.

The dynamic method dispatch can now be understood. When a reference of super class is used for calling a method at run time (which is overridden in derived class), it is checked as to which particular object the reference is referring to. It is possible that a super class reference might be referring to its own object or an object of its derived class. Now at run time, the method is called by checking the contents of the reference as to which type of object it is referring to and not by checking what type it is.

Consider the following code:

class A
{
   void show()
   {
          System.out.println("Hello from show of A");
   }
}

class B extends A
{
   void show()
   {
          System.out.println("Hello from show B");
   }
}
class C extends A
{
   void show()
   {
          System.out.println("Hello from show of C");
   }
}

In the above code, the show function of parent class A is overridden in class B and class C. Now when the function show is called as given below, the following shows which version of the show is called.

A ref = new A();
ref.show();      //show of A is called
ref = new B();
ref.show();      //show of B is called
ref = new C();
ref.show();      //show of C is called

Note: We have just used one reference ref of super class A and in which storing the objects of different classes. A full program with two methods is given below.

/*PROG 8.9 DEMO OF DYNAMIC METHOD DISPATCH */
class A
{
   void show()
   {
          System.out.println("
Hello from show of A");
   }
   void display()
   {
          System.out.println("Hello from display of A ");
   }
}
class B extends A
{
   void show()
   {
          System.out.println("
Hello from show of B");
   }
}
class C extends A

{
   void display()
   {
          System.out.println("Hello from display of C");
   }
}
class JPS11
{
   public static void main(String[] args)
   {
          A ref = new A();
          B b = new B();
          C c = new C();
          ref.show();
          ref.display();
          ref = b;
          ref.show();
          ref.display();
          ref = c;
          ref.show();
          ref.display();
   }
}
OUTPUT:

Hello from show of A
Hello from display of A
Hello from show of B
Hello from display of A
Hello from show of A
Hello from display of C

Explanation: In class A, two methods, show and display, are defined. The function show is overridden in class B but display is not. In the class C method, display is overridden but show is not. In the main function, reference b of class B is assigned to ref, which is a reference of super class A. Now when show and display are called, show of class B is called as it is overridden in class B and contents is the object of class B. The display method is not found in the class B so interpreter searches it in its super class A. It finds it there, and display of class is called. Similarly when reference c of class C is assigned to ref and when show and display are called, show of class A and display of class C are called.

8.6 HIERARCHICAL INHERITANCE REVISITED

In this type of inheritance, one class can be a parent of many other classes. For example:

images

Here class A is the base class for all three classes: B, C and D. They can share all fields, methods of class A except private members.

Suppose that a program has to deal with motor vehicles, including cars, trucks and motorcycles. The program could use named Vehicles to represent all types of vehicles. The Vehicles class could include instance variables, such as registration Number and owner, and instance method, such as transferOwnership(). These are variables and methods common to all vehicles. Three subclasses of Vehicle-Car, Truck and Motorcycle-could then be used to hold variables and methods specific to particular types of vehicles. The Car class might add an instance variable 'numberOfDoors', the Truck class might have 'numberOfAxels' and the Motorcycle class could have a Boolean variable 'hasSidecar'. The declarations of these classes in Java program would look, in outline, like the following:

class Vehicle
{
   int registrationNumber;
   String owner;
   void transferOwnerships(String newOwner)
   {
          //fucntion codes;
   }
   //other class stuff;
}
class Car extends Vehicle
{
   int numberOfDoors;
   //other class stuff;
}
class Truck extends Vehicle
{
   int numberOfAxels;
   //other class stuff;
}
class Motorcycle extends Vehicle
{
   boolean hasSidecar;
   //other class stuff;
}

images

Suppose that myCar is a variable of type Car that has been declared and initialized with the statement.

Car myCar=new Car();

Given this declaration, a program could refer to 'myCar.numberOfDoors', since 'numberOfDoors' is an instance variable in the class Car. But since class Car extends class Vehicle, a car also has all the structures and behaviour of a Vehicle. This means that 'myCar.registrationNumber', 'myCar.owner' and 'myCar. transferOwnership()' also exist.

Now, in the real world, cars, trucks and motorcycles are in fact vehicles. The same is true in a program. That is, an object of type Car or truck or Motorcycle is automatically an object of type Vehicle. This brings out the following important facts: A variable that can hold a reference to an object of class A can also hold a reference to an object belonging to any subclass of A.

The practical effect of this in the example is that an object of type Car can be assigned to a variable of type Vehicle. That is, it would be legal to write the following:

Vehicle myVehicle = myCar;

or even

Vehicle myVehicle = new Car();

After either of these statements, the variable 'myVehicle' holds a reference to a Vehicle object that happens to be an instance of the subclass, Car. The object remembers that it is in fact a Car and not just a Vehicle. The information about the actual class of an object is stored as part of that object.

On the other hand, if 'myVehicle' is a variable of type Vehicle, the assignment statement

myCar= myVehicle;

would be illegal because 'myVehicle' could refer to other types of vehicles that are not cars.

8.7 THE SUPER KEYWORD

Whenever the base class version of the function is called which is overridden in the derived class, the super keyword can be used. The super keyword always refers to the immediate base class. For example, consider the following code:

class A
{
   void show()
   {
          System.out.println("Hello from show of A");
   }
}
class B extends A
{
   void show()
   {
          show(); //will lead to recursion
          System.out.println("Hello from show of B");
   }
}

In the above case, inside the show of class B, if show (as written) is simply written, it will call itself, and recursion will follow. To call the base class version, super.show can be written, which means show of class A will be called. Super can also be used to any of the method or field of the base class or for calling constructor. See the example given below. More examples can be found later in this chapter.

/*PROG 8.10 DEMO OF SUPER VER 1*/
class A
{
   int num;
   void show()
   {
          System.out.println("
Hello from A num := " + num);
   }
}
class B extends A
{
   int num = 80;
   void show()
   {
          super.num = 50;
          super.show();
          System.out.println("
Hello from B num := " + num);
   }
}
class JPS12
{
   public static void main(String args[])
   {
          B obj = new B();
          obj.show();
   }
}
OUTPUT:

Hello from A num := 50
Hello from B num := 80

Explanation: The expression super.num represents num of the immediate base class, i.e., class A. Similarly super.show represents show of class A.

8.8 CONSTRUCTOR AND INHERITANCE

This section discusses how the constructors are called when they are present both in base and derived classes, and how the values are passed from derived class to base class. Assume a small example of single level inheritance in which class A is inherited by class B . Both the classes have their default constructors. When an object of class B is created, it calls the constructor of class B, but as class B has got A as its parent class, constructor of class A will be called first, followed by that of class B. This is so because when derived class has inherited base class, obviously it will be using the data member from base class. Now without calling the constructor of base class, data members of base class will not be initialized and if derived class uses the uninitialized data members of base class, unexpected result may follow. Calling a constructor of base class first allows base class to properly wet up its data members so that they can be used by derived classes.

/*PROG 8.11 DEMO OF CONSTRUCTOR IN INHERITANCE VER 1 */
class first
{
   first()
   {
          System.out.println("
 Con of first called");
   }
}
class second extends first
{
   second()
   {
          System.out.println(" Con of second called");
   }
}
class JPS13
{
   public static void main(String[]args)
   {
          second obj = new second();
   }
}
OUTPUT:

Con of first called
Con of second called

Explanation: The new second() causes constructor of second class to be called. But as first is the base class of second class, constructor of first class will be called first, followed by that of second class.

/*PROG 8.12 CONSTRUCTOR AND MULTILEVEL INHERITANCE */
class first{
   first()
   {
          System.out.println(" 
Cons of first called");
   }
}
class second extends first{
   second()
   {
          System.out.println(" 
Cons of second called ");
   }
}
class third extends second
{
   third()
   {
          System.out.println(" 
Cons of third called ");
   }
}
class JPS15
{
   public static void main(String[] args)
   {
          third obj = new third();
   }
}
OUTPUT:

Cons of first called
Cons of second called
Cons of third called

Explanation: Class second is the base class of class third and class first is the base class of class second. So, constructor of classes first, second and third are called in order.

/*PROG 8.13 PARAMETERIZED CONSTRUCTOR WITHIN INHERITANCE VER 1 */
class first
{
   private int fa;
   first(int x)
   {
          fa = x;
          System.out.println("
Cons of first called ");
   }
   void fshow()
   {
          System.out.println("fa= " + fa);
   }
};
class second extends first
{
   private int sa;
   second(int a, int b)
   {
          super(a);
          sa = b;
          System.out.println("
Cons of second called");
   }
   void sshow()
   {
          fshow();
          System.out.println("sa = " + sa);
   }
}
class JPS16

{
   public static void main(String[] args)
   {
          second s = new second(20, 30);
          s.sshow();
   }
}
OUTPUT:

Cons of first called
Cons of second called
fa = 20
sa = 30

Explanation: When statement second s = new second (20, 30); executes, object s calls the parameterized constructor of class second and passes parameters 20 and 30 . Inside the constructor, they are assigned to a and b, respectively. Before entering into the body of constructor, super(a) calls the constructor of class first and passes a as argument. Inside the class first, it is assigned to fa and con of first called is displayed. When control returns, it enters into the body of the constructor and assigns b to sa. When sshow of class second is called, it first calls the fshow of class first. Again note that super(a) is the first statement in the constructor of the derived class.

In the earlier program, there are two int parameterized constructor in the derived class but this is not necessary. We can also have a single int argument constructor and yet passing a single int value by doing same manipulation over the single int data. As long as the required type and number of parameters are passed in the super class constructor, no problem arises, no matter where they have come from. For example, consider a section of the code rewritten from the above program:

second (int a)
{
   super(a%10);
   sa=a;
   System.out.println("Cons of second called");
}

In the main, the constructor can be used as follows:

second s = new second (46);

The above call assigns 6 to fa of first class (due to 46%10) and 46 to sa.

/*PROG 8.14 PARAMETERIZED CONSTRUCTOR WITHIN INHERITANCE VER 2 */
class first
{
   int num;
   first(int x)
   {
          num = x;
          System.out.println(" 
Cons of first called");
          System.out.println(" num := " + num);
   }

}
class second extends first
{
   String str;
   second(int d, String s)
   {
          super(d);
          str = s;
          System.out.println("
Cons of second called");
          System.out.println("str := " + str);
   }
}
class third extends second
{
   private char cnum;
   third(int d, String s, char c)
   {
          super(d, s);
          cnum = c;
          System.out.println("
Cons of third called ");
          System.out.println("cnum := " + c);
   }
}
class JPS17
{
   public static void main(String[] args)
   {
          new third(2345, "Demo", 'J'),
   }
}
OUTPUT:

Cons of first called
num := 2345

Cons of second called
str := Demo

Cons of third called
cnum := J

Explanation: In parameterized constructor with inheritance, the derived class constructor must provide initial values to the constructors of the base class. In the program, class second is the base class for class third and class first is the base class for class second. When constructor of class third is called from the main it is written as follows:

new third(2345, "Demo", 'J'),

where 2345 is assigned to d, "Demo" is assigned to s and 'J' is assigned to c. As second class is the base class of class third, the first line super(d, s) calls the constructor of the base class second and passes arguments d and s. Inside the constructor of second class, d and s are assigned to d and s. Now as class first is the base class for class second, the first line in the constructor of second class super (d) calls constructor of class first and passes d as argument. Inside the constructor of class first, this d is copied to x which is assigned to num. Control returns back to constructor of second class and str = s executes. When constructor of class second returns, it returns to the statement cnum = c. Rest is simple to understand.

Note: In inheritance, in the constructor of the derived class, if you are using the super keyword then it must be the first statement inside the constructor of the derived class.

8.9 OBJECT SLICING

Object slicing is a process of removing off the derived portion of the object when an object of derived class is assigned to a base class object. Only the base class data are copied to derived class object. Consider the following two classes:

class A
{
   int Ax, Ay;
}
class B extends A
{
   int Bx;
}

Through inheritance, data members Ax and Ay of class A are copied to class B; when in the main it is written as follows:

B b1 = new B();
A a1 = new A();
a1 = b1;

Only the data members of object b1, which were inherited from class A, are assigned to object a1. The data member Bx of object b1 is not copied. In other words, object b1 was sliced off.

/*PROG 8.15 DEMO OF OBJECT SLICING VER 1*/
class demo
{
   void show_demo()
   {
          System.out.println("
Hello from show of demo");
   }
};
class der_demo extends demo
{
   void show_der()
   {
          System.out.println("Hello from show of der_demo");
   }
}
class JPS18
{
   public static void main(String[] args)
   {
          demo d1 = new demo();
          der_demo d2 = new der_demo();
          d1 = d2;
          d1.show_der();
   }
}
OUTPUT:

C:JPSch8>javac JPS18.java
JPS18.java:23: cannot find symbol
symbol : method show_der()
location: class demo
                 d1.show_der();
                  ^
1 error

Explanation: In the main function, when an object d2 of derived class der_demo is assigned to an object d1 of class demo, only the inherited portion of base class is assigned to d1. Although functions are usually not part of the object yet a function of one class can be called from object of that class or from objects of derived class. Here, from d1, the function show_der of derived class cannot be called.

/*PROG 8.16 DEMO OF OBJECT SLICING VER 2 */
class demo
{
   int bx, by;
   demo(int x, int y)
   {
          bx = x;
          by = y;
   }
   demo() { }
};
class der_demo extends demo
{
   int dx;
   der_demo(int x, int y, int z)
   {
          super(x, y);
          dx = z;
   }
}
class JPS19
{
   public static void main(String[] args)
   {
          der_demo d2 = new der_demo(10, 20, 30);
          demo d1 = new demo();
          d1 = d2;
          System.out.println(d1.bx + "	" + d1.by + "	" +
                                     d1.dx);
   }
}
OUTPUT:

C:JPSch8>javac JPS19.java
JPS19.java:28: cannot find symbol
symbol       : variable dx
location : class demo
System.out.println(d1.bx + "	" + d1.by + "	" + d1.dx);
                                                  ^
1 error

Explanation: The class demo consists of two data members bx and by and class der_demo with just one data member dx. When in the main function, d1 = d2 is written , only the inherited data members bx and by are assigned to object d1. The data member dx from d2 is not assigned to d1. In effect, object d2 gets sliced. So dx cannot be called from an object of demo class.

8.10 FINAL CLASS

A final class is a class which is declared final by placing the keyword final before class definition. A final class has the property that it cannot be inherited. One example of final class is System class defined in package java.lang.

When you say that an entire class is final, you state that you do not want to inherit from this class or allow anyone else to do so. In other words, for some reason, the design of your class is such that there is never a need to make any changes, or for safety or security reasons, you do not want sub-classing.

Note that the fields of a final class can be final depending on how you write. The same rules apply to final for fields regardless of whether the class is defined as final. However, because it prevents inheritance, all methods in a final class are implicitly final since there is no way to override them. An example follows:

final class demo
{
     float num = 45.50f;
     String F = "Final";
     void fix() { }
}

8.11 ABSTRACT CLASS

An abstract class is the one that is not used to construct objects, but only as a basis for making subclasses. It exists only to express the common properties of all its subclasses. An abstract class is a class that leaves one or more method implementations unspecified by declaring one or more method abstract. An abstract method has nobody, i.e., no implementation (partially true). A subclass is required to override the method and provide an implementation. Hence, an abstract class is incomplete and cannot be instantiated, but can be used as a base class.

An abstract class usually has one or more abstract methods. This is a method that is incomplete; it has only a declaration and no method body. The syntax for an abstract method declaration is as follows:

abstract void fun();

A class containing abstract methods is called an abstract class. If a class contains one or more abstract methods, the class itself must be qualified as abstract. (Otherwise, the compiler gives an error message.) Objects of an abstract class cannot be created so an abstract class must be inherited by some other class. The derived class must provide the implementation of all abstract methods declared in the abstract class. If the derived class does not provide implementation for the abstract functions, it must be declared as abstract.

To create a class as abstract, abstract keyword simply needs to be written before the class keyword as follows:

abstract class demo
{
   optional abstract method signatures;
}

It is possible to create a class as abstract without including any abstract methods. This is useful when there is a class in which it does not make sense to have any abstract methods, and yet any instances of that class is required to be prevented.

If an abstract class is incomplete, what is the compiler supposed to do when someone tries to make an object of that class? It cannot safely create an object of an abstract class so one gets an error message from the compiler. This way, the compiler ensures the purity of the abstract class, and one need not worry about misusing it. Creating a reference of an abstract class is perfectly valid. A reference can hold the objects of other derived classes but can only functions which are part of the base class. A reference cannot call any function of the derived class. This will be shown later on.

If one inherits from an abstract class and wants to make objects of the new type, method definitions must be provided for all the abstract methods in the base class. Otherwise (and one may choose not to), the derived class is also abstract, and the compiler will force one to qualify that class with the abstract keyword.

In short, note the following points about abstract class:

1.   An abstract class is declared using the keyword abstract.

2.   It may or may not contain abstract methods.

3.   An abstract class must be inherited by some other class.

4.   If the derived class does not provide the implementation of any abstract method present in an abstract class, the derived class must be declared as abstract.

5.   Objects of an abstract class cannot be created, but reference can be created.

6.   Through reference of abstract class, only methods of the abstract class implemented in the derived class can be called.

7.   Abstract keyword cannot be applied to static methods or constructor.

A few example programs of abstract class are given below.

/*PROG 8.17 DEMO OF ABSTRACT CLASS VER 1 */
abstract class Base
{
   abstract void show();
}
class first extends Base

{
   void show()
   {
          System.out.println("

show of first");
   }
}
class second extends Base
{
   void show()
   {
          System.out.println("
Show of second");
   }
}
abstract class third extends Base
{
}
class JPS20
{
   public static void main(String[] args)
   {
          Base ref = new first();
          ref.show();
          ref = new second();
          ref.show();
   }
}
OUTPUT:

show of first
Show of second

Explanation: In the program, an abstract class Base is created. In the class, we have an abstract method demo, which all derived classes must give the implementation. The class first and second inherit the Base class and provide the implementation of show method. The class third does not provide the implementation, so it must be declared as abstract.

In the main function, a reference of class Base named ref is created. In this ref, the object of class first is assigned and call the show was called . An object of class first can also be created and the show called as follows:

first f = new first();
f.show();

The same reference ref of Base class is then used for second class object and show is called. Note it would be an error to try to instantiate an object of an abstract type.

Base obj = new Base (); // ERROR

That is, operator new is invalid when applied to an abstract class.

/*PROG 8.18 DEMO OF ABSTRACT CLASS VER 2 */
abstract class Base
{
   void show()
   {
          System.out.println("
Show of base");
   }
}
class first extends Base
{
   void show()
   {
          super.show();
          System.out.println(" 
show of first");
   }
}
class JPS21
{
   public static void main(String args[])
   {
          Base ref = new first();
          ref.show();
          ref = new second();
          ref.show();
   }
}
OUTPUT:

Show of base
show of first
Show of second

Explanation: It was mentioned earlier that an abstract class can have non-abstract methods also. In the program in class Base, there is a method show which is having the body and not abstract. But being an abstract class, an object of this class cannot be instantiated. So this class must be inherited by some other class, and the object of that class can call the method show.

The class first inherits the class Base and overrides the show method. The base class version of show is called by using the super keyword. The class second simply inherits the class Base and is empty. In the main function, we create reference of class Base is created and the method show was called. Note, ref.show calls the method show of class first and not of its own, as the object stored is of class first. Second time, the ref holds the reference of an object of class second. When the method show is called as ref.show, first, the show method is searched in the class second. When it does not find one there, it looks for the method in the Base class. It finds the method there and calls it.

/*PROG 8.19 SHOWING THE FLYING STATUS OF VARIOUS INSECTS */
abstract class Insect
{
   public abstract void flystatus();
}
class Cockroach extends Insect
{
   public void flystatus()
   {
          System.out.println("
Cockroach can fly");
   }
}
class Termite extends Insect
{
   public void flystatus()
   {
          System.out.println("
Termite cannot fly");
   }
}
class Grasshopper extends Insect
{
   public void flystatus()
   {
          System.out.println("
Grasshopper can fly");
   }
}
class Ant extends Insect
{
   public void flystatus()
   {
          System.out.println("
Ant cannot fly");
   }
}
class JPS24
{
   public static void main(String[] args)
   {
          Insect ptr[] = new Insect[4];
          ptr[0] = new Cockroach();
          ptr[1] = new Termite();
          ptr[2] = new Grasshopper();
          ptr[3] = new Ant();
          for (int i = 0; i < ptr.length; i++)
          ptr[i].flystatus();
   }
}

OUTPUT:

Cockroach can fly
Termite cannot fly
Grasshopper can fly
Ant cannot fly

Explanation: The abstract class Insect declares one abstract function flystatus. Any class which inherits this class has to redefine this function and tell his/her flying status, i.e., whether he/she can fly or not. The class Insect inherits four different classes: Cockroach, Termite, Grasshopper and Ant. Each class does provide implementation of function flystatus. In the main function, an array of references of class Insect type is created. In each reference of this array, the objects of various derived classes are assigned as shown below:

ptr[0] = new Cockroach();
ptr[1] = new Termite();
ptr[2] = new Grasshopper();
ptr[3] = new Ant();

In the for loop, flystatus function is called using this Insect array ptr, respective flystatus functions of each class are called.

/*PROG 8.20 DEMO OF ABSTRACT CLASS VER 5 */
abstract class Figure
{
   abstract double area();
   abstract int tellsides();
   double s1, s2;
   Figure(double a, double b)
   {
          s1 = a;
          s2 = b;
   }
}
class Rectangle extends Figure
{
   final int sides = 4;
   Rectangle(double a, double b)
   {
          super(a, b);
   }
   int tellsides()
   {
          return sides;
   }
   double area()
   {
          return s1 * s2;
   }
}
class Triangle extends Figure
{
   final int sides = 3;
   Triangle(double a, double b)
   {
          super(a, b);
   }
   int tellsides()
   {
          return sides;
   }
   double area()
   {
          return s1 * s2 / 2;
   }
}
class JPS25
{
   public static void main(String[] args)
   {
          Figure ref = new Rectangle(10, 15);
          double ar_fig = ref.area();
          int s = ref.tellsides();
          System.out.println("
Area of Rectangle:="+ ar_fig);
          System.out.println(" Number of sides := " + s);
          ref = new Triangle(5, 4);
          ar_fig = ref.area();
          s = ref.tellsides();
          System.out.println("Area of Triangle := " + ar_fig);
          System.out.println(" Number of sides := " + s);
   }
}

OUTPUT:

Area of Rectangle      := 150.0
Number of sides  := 4
Area of Triangle := 10.0
Number of sides  := 3

Explanation: In the program, there is an abstract class figure. The class has two data members, s1 and s2, which stand for two sides of the figure. The class has two abstract methods: area and tellsides. Each geometrical figure which inherits this class must calculate the area and tell the number of sides it has. The class also has constructor which takes two parameters of double type and assign the values to s1 and s2.

The class is inherited by two classes, Rectangle and Triangle, which provide the implementation of area and tellside. Both use a final member side, which represents number of sides a figure has.

In the main object of class, Rectangle and Triangle are created using constructors, and dimension of sides is passed. In both the calls, Rectangle (10, 15) and Triangle (5, 4), constructor of Figure class is called and s1 and s2 get their values. Note that references to object of Rectangle and Triangle class are handled using a reference to Figure class. Rest is simple to understand.

8.12 PONDERABLE POINTS

1.   Java does not support multiple inheritance.

2.   For inheriting a class to another class, Java uses the extend keyword.

3.   In Java, there is no public, private or protected inheritance.

4.   Method overriding is redefining the function of base class in derived class with the same signature.

5.   A base class reference can hold the reference of a derived class object.

6.   The abstract keyword makes a class abstract whose object cannot be instantiated but references can be.

7.   An abstract class must be inherited by another class to make use of it.

8.   An abstract class can have abstract as well as non-abstract methods in it.

9.   An abstract method must not have body.

REVIEW QUESTIONS

1.   What is the difference between composition (has-a) and inheritance (is-a)?

2.   What is the difference between overriding and overloading a method?

3.   Describe the syntax of single inheritance in Java.

4.   What is inheritance and what are its uses?

5.   What are the rules for abstract class?

6.   When do we declare a variable, method, or class final?

7.   When do we declare a method or class abstract?

8.   Discuss the different level of access protection with example.

9.   Create a base class called Shape, it contain two methods getxyvalue() and showxyvalue() for accepting co-ordinates and to displaying the same. Create a subclass called Rectangle. It also contains a method to display the length and breadth of the rectangle called showxyvalue(). Use the overriding concept.

10. Write a class called TV with the following attribute. Name of the company and Screen size using super keyword and Inheritance to create a color TV class, it has a attribute TVtype also a BW TV class it is also have TVtype attribute in Boolean data type.

11. Write a program that creates an abstract class called dimension. Create two subclasses, rectangle and triangle, that include appropriate methods for both the subclasses that calculate and display the area of the rectangle and triangle.

12. Write a program that has an overloaded method. The first method should accept no arguments, the second method will accept one string and the third method should display the message. "Welcome to java" once. The second method should display the message "Welcome to polymorphism" twice and the third method should display the message "Welcome to overloading" three times.

13. What message does Java give when you put an abstract method inside a class which is not, in itself, declared abstract?

14. Why an abstract method cannot be defined as final? Justify with example.

15. Why an abstract method cannot be defined as static? Justify with example.

16. Imagine a publishing company that markets both book and audiocassette versions of its works. Create a class publication that stores the title (a string) and price (type float) of publication. From this class, derive two classes: book, which adds a page count (type int), and tape, which adds a playing time in minutes (type float). Each of these three classes should have a getdata() function to get its data from the user as the keyboard, and a putdata() function to display its data.
Write a main() program to test the book and tape classes by creating instance of them, asking the user to fill in data with getdata(), and then displaying data with putdata().

17. Start with the publication, book and tape classes of Exercise-16. Add a base class sales that holds an array of three floats so that it can record the dollar sales of a particular publication for the last three months. Include a getdata() function to get three sales amounts from the user, and a putdata() function to display the sales figures. After the book and tape classes they are derived from both publication and sales. An object of class book or tape should input and output sales data along with its other data. Write a main() function to create a book object and a tape object and exercise their input/output capabilities.

18. Declare a class Vehicle. From this class derive two_wheeler, three_wheeler and four_wheeler class. Display properties of each type of vehicle using member function of the class.

Multiple Choice Questions

1.   Java does not support

(a) single inheritance

(b) multilevel inheritance

(c) multiple inheritance

(d) hierarchical inheritance

2.   For inheriting a class to another class Java uses the keyword

(a) super

(b) this

(c) final

(d) extends

3.   The super keyword always refers to the

(a) derived class

(b) any base class

(c) immediate base class

(d) none of the above

4.   One example of final class is __________ class defined in the package java.lang is

(a) system class

(b) integer class

(c) abstract class

(d) none of the above

5.   Final class has the property that

(a) cannot be inherited

(b) can be inherited

(c) can be inherited publicly

(d) none of the above

6.   An abstract class is declared using the keyword abstract that

(a) must contain abstract method

(b) cannot contain abstract method

(c) may or may not contain abstract method

(d) none of the above

7.   Abstract keyword cannot be applied to

(a) destructor

(b) static methods or constructor

(c) derived class

(d) none of the above

8.   String toString() method is used to

(a) wait on another string of execution

(b) return a string that describes the object

(c) call before an unused object is recycled

(d) none of the above

9.   Object clone() method is used to

(a) create a new object that is the same as the object being cloned

(b) determine whether one object is equivalent to another

(c) both (a) and (b) are correct

(d) none of the above

10. The code given below

class demo1{ }
class demo2 extends demo1
{ }
demo2 d2 = new demo1();

(a) is not valid

(b) is perfectly valid

(c) is valid using abstract class

(d) none of the above

KEY FOR MULTIPLE CHOICE QUESTIONS

1.   c

2.   d

3.   c

4.   a

5.   a

6.   c

7.   b

8.   b

9.   a

10. b

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.86.18