CS F213 Objected Oriented Programming Labsheet 5

Spring 2024

Java Inheritance

It is the mechanism in Java by which one class is allowed to inherit the features (fields and methods) of another class. In Java, Inheritance means creating new classes based on existing ones. A class that inherits from another class can reuse the methods and fields of that class. In addition, you can add new fields and methods to your current class as well.

Single Inheritance

Example

import java.io.*;
// Base or Super Class

class Employee {
	int salary = 60000;
}

// Inherited or Sub Class
class Engineer extends Employee {
	int benefits = 10000;
}

class Main {
	public static void main(String args[])
	{
		Engineer E1 = new Engineer();
		System.out.println("Salary : " + E1.salary 
						+ "\nBenefits : " + E1.benefits);
	}
    //salary is accessible through Engineer class object as it is the subclass of Employee
}

Output

Salary : 60000
Benefits : 10000

This was an example of Single inheritance. When a class inherits another class, it is known as a single inheritance.

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.

import java.io.*;

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 Main{  
    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

import java.io.*;
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 Main{  
    public static void main(String args[]){  
        Cat c=new Cat();  
        c.meow();  
        c.eat();
}}      

Output

meowing...
eating...

but here if we call c.bark(); in Main class then it would produce the following error:

Main.java:19: error: cannot find symbol
        c.bark();
         ^
  symbol:   method bark()
  location: variable c of type Cat
1 error

This implies Dog and Cat class can inherit the properties of Animal class as they extend it but they can't access variables and methods of each other as they are not related to each other.

Multiple Inheritance

To reduce the complexity and simplify the language, multiple inheritance is not supported in java. Consider a scenario where A, B, and C are three classes. The C class inherits A and B classes. If A and B classes have the same method and you call it from child class object, there will be ambiguity to call the method of A or B class.

Java renders compile-time error if you inherit 2 classes

class A{  
    void msg(){
        System.out.println("Hello");}  
}  
class B{  
    void msg()
    {System.out.println("Welcome");}  
}  
class C extends A,B{ 
    public static void main(String args[]){  
        C obj=new C();  
        obj.msg();
}  
}  

Output

Main.java:7: error: '{' expected
class C extends A,B {  
                 ^
1 error

Java super keyword

The super keyword refers to superclass (parent) objects. It is used to call superclass methods, and to access the superclass constructor.

The most common use of the super keyword is to eliminate the confusion between superclasses and subclasses that have methods with the same name.

super can be used with (In below examples it is assumed Main class is created and an object of subclass is created)

  1. Variables

class Vehicle { 
    int maxSpeed = 120; 
}  
class Car extends Vehicle { 
    void display() {
        System.out.println("Maximum Speed: "
                           + super.maxSpeed); 
    } 
} 

Output

Maximum Speed: 120
  1. Methods

class Person { 
    void message() {
        System.out.println("This is person class\n"); 
    } 
} 
class Student extends Person { 
    void message() {
        System.out.println("This is student class"); 
    } 
    void display() {
        message(); 
        super.message(); 
    } 
} 

Output

This is student class
This is person class
  1. Constructors

class Person { 
    Person() {
        System.out.println("Person class Constructor"); 
    } 
}  
class Student extends Person { 
    Student() {
        super(); 
        System.out.println("Student class Constructor"); 
    } 
} 

Output

Person class Constructor
Student class Constructor

Method Overriding in Java

If subclass (child class) has the same method as declared in the parent class, it is known as method overriding in Java. In other words, If a subclass provides the specific implementation of the method that has been declared by one of its parent class, it is known as method overriding.

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

class Vehicle{  
  //defining a method  
  void run(){
    System.out.println("Vehicle is running");}  
}  
//Creating a child class  
class Bike2 extends Vehicle{  
  //defining the same method as in the parent class  
  void run(){
    System.out.println("Bike is running");}
}
class Main{
  public static void main(String args[]){  
    Bike2 obj = new Bike2();
    obj.run();
    }  
}  

Output

Bike is running

Java method overriding is mostly used in Runtime Polymorphism

In the above program if we want to print "Vehicle is running", we can use super.run();

Method overriding forms the basis for one of Java’s most powerful concepts: 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 important because this is how Java implements run-time polymorphism.

Abstract Classes

There are situations in which you will want to define a superclass that declares the structure of a given abstraction without providing a complete implementation of every method. That is, sometimes you will want to create a superclass that only defines a generalized form that will be shared by all of its subclasses, leaving it to each subclass to fill in the details.

Example

import java.io.*;

abstract class Subject { //abstract class
	Subject() { 
	System.out.println("Learning Subject"); 
	}

	abstract void syllabus(); //abstract method

	void Learn(){
		System.out.println("Preparing Right Now!");
	}
}

class IT extends Subject {
void syllabus(){
	System.out.println("C , Java , C++");
}
}

class Main{
	public static void main(String[] args) {
		IT x=new IT();
	
		x.syllabus();
		x.Learn();
	}
}

Output

Learning Subject
C , Java , C++
Preparing Right Now!

Explanation:

In Java, when you create an object of a class, the constructor of that class is called. In the case of the line IT x = new IT();, the following happens:

  1. Memory is allocated for an object of the IT class.

  2. The constructor of the IT class is called, which in turn calls the constructor of its superclass (Subject in this case) because every constructor implicitly or explicitly invokes the constructor of its superclass. In the Subject constructor, you have the statement System.out.println("Learning Subject");, which prints "Learning Subject" to the console.

Even though the object is declared as type IT, the constructor of the superclass (Subject) is still called because Java ensures that the constructors of all superclasses in the inheritance hierarchy are executed when an object is created. This is part of the initialization process to ensure that the object is properly set up.

So, when you create an object of the IT class using IT x = new IT(), the constructor of both IT and its superclass Subject are executed, and you see "Learning Subject" printed to the console.

Using final to avoid Overriding and Inheritence

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.

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, it is illegal to declare a class as both abstract and final since an abstract class is incomplete by itself and relies upon its subclasses to provide complete implementations.

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!");
 }
}
//here is an example of final class
final class A {
 //...
}

Java Package

A java package is a group of similar types of classes, interfaces and sub-packages. Package in java can be categorized in two forms, built-in package and user-defined package. There are many built-in packages such as java, lang, awt, javax, swing, net, io, util, sql etc.

The package keyword is used to create a package in java.

package mypack;  
public class Simple{  
 public static void main(String args[]){  
    System.out.println("Welcome to package");  
   }  
}  

How to compile java package?

You need to follow the syntax given below:

javac -d directory javafilename

Example

javac -d . Simple.java  

The -d switch specifies the destination where to put the generated class file. You can use any directory name like /home (in case of Linux), d:/abc (in case of windows) etc. If you want to keep the package within the same directory, you can use . (dot).

How to run java package program?

To Compile: javac -d . Simple.java

To Run: java mypack.Simple

Output

Welcome to package

Also you must be well aware by now how to import packages in java, it is done using the import keyword.

Interfaces

Another way to achieve abstraction in Java, is with interfaces. An interface is a completely "abstract class" that is used to group related methods with empty bodies

// interface
interface Animal {
  public void animalSound(); // interface method (does not have a body)
  public void run(); // interface method (does not have a body)
}

To access the interface methods, the interface must be "implemented" (kind of like inherited) by another class with the implements keyword (instead of extends). The body of the interface method is provided by the "implement" class

// Interface
interface Animal {
  public void animalSound(); // interface method (does not have a body)
  public void sleep(); // interface method (does not have a body)
}

// Pig "implements" the Animal interface
class Pig implements Animal {
  public void animalSound() {
    // The body of animalSound() is provided here
    System.out.println("The pig says: wee wee");
  }
  public void sleep() {
    // The body of sleep() is provided here
    System.out.println("Zzz");
  }
}

class Main {
  public static void main(String[] args) {
    Pig myPig = new Pig();  // Create a Pig object
    myPig.animalSound();
    myPig.sleep();
  }
}

Output

The pig says: wee wee
Zzz

Notes on Interfaces:

  1. Like abstract classes, interfaces cannot be used to create objects (in the example above, it is not possible to create an "Animal" object in the Main class)

  2. Interface methods do not have a body - the body is provided by the "implementing" class

  3. On implementation of an interface, you must override all of its methods, or the implementing class must be declared abstract

  4. Interface methods are by default abstract and public

  5. Interface attributes are by default public, static and final

  6. An interface cannot contain a constructor (as it cannot be used to create objects)

WHY INTERFACES?

Java does not support "multiple inheritance" (a class can only inherit from one superclass). However, it can be achieved with interfaces, because the class can implement multiple interfaces. Note: To implement multiple interfaces, separate them with a comma:

interface FirstInterface {
  public void myMethod(); // interface method
}

interface SecondInterface {
  public void myOtherMethod(); // interface method
}
//multiple inheritence using interfaces
class DemoClass implements FirstInterface, SecondInterface {
  public void myMethod() {
    System.out.println("Some text..");
  }
  public void myOtherMethod() {
    System.out.println("Some other text...");
  }
}

class Main {
  public static void main(String[] args) {
    DemoClass myObj = new DemoClass();
    myObj.myMethod();
    myObj.myOtherMethod();
  }
}

Output

Some text..
Some other text...

JDK 8 and 9 onwards interfaces are allowed to have private methods and default method implementations.

Default Interface Methods

A default method lets you define a default implementation for an interface method. In other words, by use of a default method, it is possible for an interface method to provide a body, rather than being abstract.

Example

public interface MyIF {
 // This is a "normal" interface method declaration.
 // It does NOT define a default implementation.
 int getNumber();
 // This is a default method. Notice that it provides
 // a default implementation.
 default String getString() {
 return "Default String";
 }
}
class MyIFImp implements MyIF {
 // Only getNumber() defined by MyIF needs to be implemented.
 // getString() can be allowed to default.
 public int getNumber() {
 return 100;
 }
}
class Main {
 public static void main(String[] args) {
 MyIFImp obj = new MyIFImp();
 // Can call getNumber(), because it is explicitly implemented by MyIFImp.
 System.out.println(obj.getNumber());
 // Can also call getString(), because of default implementation.
 System.out.println(obj.getString());
 }
}

Output

100
Default String

Exception Handling

When executing Java code, different errors can occur: coding errors made by the programmer, errors due to wrong input, or other unforeseeable things.

When an error occurs, Java will normally stop and generate an error message. The technical term for this is: Java will throw an exception (throw an error).

Java try and catch

The try statement allows you to define a block of code to be tested for errors while it is being executed.

The catch statement allows you to define a block of code to be executed, if an error occurs in the try block. The try and catch keywords come in pairs:

try {
  //  Block of code to try
}
catch(Exception e) {
  //  Block of code to handle errors
}

Example

public class Main {
  public static void main(String[ ] args) {
    int[] myNumbers = {1, 2, 3};
    System.out.println(myNumbers[10]); // error!
  }
}

Output will be

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10
        at Main.main(Main.java:4)

If an error occurs, we can use try...catch to catch the error and execute some code to handle it:

Modified code

public class Main {
  public static void main(String[ ] args) {
    try {
      int[] myNumbers = {1, 2, 3};
      System.out.println(myNumbers[10]);
    } catch (Exception e) {
      System.out.println("Something went wrong.");
    }
  }
}

Output

Something went wrong.

Later we will discuss more about Exception handling and keywords like finally, throw and throws.

Exercises

Exercise 1: (Inheritance)

You are required to implement a simple program for managing vehicles. Create a base class Vehicle with the following attributes:

make (String) - representing the make of the vehicle model (String) - representing the model of the vehicle year (int) - representing the manufacturing year of the vehicle

Implement a parameterized constructor in the Vehicle class that initializes these attributes. Also, provide a method named displayDetails in the Vehicle class that displays the details of the vehicle.

Now, create a derived class Car that inherits from the Vehicle class. The Car class should have an additional attribute:

numDoors (int) - representing the number of doors of the car Implement a parameterized constructor in the Car class that initializes both the attributes of the base class (make, model, year) and the additional attribute (numDoors). Override the displayDetails method in the Car class to include information about the number of doors.

In the main method of the program, create an object of the Car class, take user input for the make, model, year, and number of doors, and display the details using the displayDetails method of the Car class.

Sample Input

Enter car make: Toyota
Enter car model: Corolla
Enter manufacturing year: 2022
Enter number of doors: 4

Sample Output

Car Details:
Make: Toyota
Model: Corolla
Year: 2022
Number of Doors: 4

Exercise 2: (Abstract class and Overriding)

Develop a program for managing various shapes in a geometric application. Implement an abstract class Shape with the following attributes and methods:

Attributes: shapeName (String) - representing the name of the shape. color (String) - representing the color of the shape.

Methods: abstract double calculateArea() - to be implemented by the derived classes for calculating the area of the shape. void displayDetails() - to display the details of the shape, including its name, color, and area. Derive two classes, Circle and Rectangle, from the Shape class.

Circle Class:

Include an additional attribute radius (double) for representing the radius of the circle. Implement the calculateArea method to calculate the area of the circle using the formula: area = π * radius * radius. Override the displayDetails method to include information about the radius.

Rectangle Class:

Include additional attributes length and width (both double) for representing the length and width of the rectangle. Implement the calculateArea method to calculate the area of the rectangle using the formula: area = length * width. Override the displayDetails method to include information about the length and width.

In the main method of the program, create objects of the Circle and Rectangle classes, take user input for shape details (name, color, and specific dimensions), and display the details of each shape.

Sample Input

Enter Circle details:
Shape Name: Circle
Color: Blue
Radius: 5.0

Enter Rectangle details:
Shape Name: Rectangle
Color: Red
Length: 8.0
Width: 6.0

Sample Output

Shape Details:
--------------
Circle
Color: Blue
Radius: 5.0
Area: 78.54

Rectangle
Color: Red
Length: 8.0
Width: 6.0
Area: 48.0

Exercise 3: (Interfaces and Multiple Inheritance)

Develop a program to manage a zoo that houses different types of animals. Implement an interface named Animal with the following methods:

void eat() - representing the eating behavior of the animal. void makeSound() - representing the sound the animal makes.

Now, create two default interfaces, Swim and Fly, with the following methods:

void swim() - representing swimming behavior. void fly() - representing flying behavior.

The methods should be implemented inside the interface only as they are default

Create classes for different types of animals, ensuring that they implement the Animal interface. Additionally, some animals may implement the Swim or Fly interfaces based on their characteristics.

Fish Class:

Implement the Animal and Swim interfaces. Include an additional method breatheUnderwater() to represent the characteristic of breathing underwater.

Bird Class:

Implement the Animal and Fly interfaces. Include an additional method layEggs() to represent the characteristic of laying eggs.

In the main method of the program, create objects of different animal classes, call their respective methods, and demonstrate their behaviors. Ensure that the program showcases the usage of interfaces, their implementation in classes, and multiple inheritance using interfaces.

Sample Output

Fish:
Eating...
Making sound...
Swimming...
Breathing underwater...

Bird:
Eating...
Making sound...
Flying...
Laying eggs..

Last updated