What is Inheritance in Java?

What is Inheritance in Java

Inheritance is a fundamental concept in object-oriented programming (OOP) that allows classes to inherit characteristics and behaviors from other classes. 

In Java, inheritance is implemented using the extends keyword, which allows a subclass to inherit methods and variables from a superclass. This results in code reuse, as the subclass can leverage the functionality of the superclass and add its own functionality.

In this article, we will cover the following topics related to inheritance in Java:

• What is inheritance in Java?

• Types of inheritance in Java

• Advantages of inheritance in Java

• How to implement inheritance in Java

• The super keyword in Java

• Method overriding in Java

• Final keyword in Java

• Abstract classes in Java

• Interfaces in Java

• Differences between abstract classes and interfaces

What is inheritance in Java?

Inheritance is a mechanism in Java that allows a class to inherit characteristics and behaviors from another class. The class that inherits from another class is called a subclass or derived class, and the class that is inherited from is called a superclass or base class. 

Inheritance is one of the pillars of OOP, along with encapsulation, polymorphism, and abstraction.

With inheritance, a subclass can use the methods and variables of its superclass, which allows for code reuse and avoids duplicating code. The subclass can also add its own methods and variables, or override methods of the superclass to customize their behavior.

Inheritance creates a hierarchy of classes, where subclasses inherit from superclasses, and can be used to model real-world relationships between objects.

Types of Inheritance in Java

In Java, there are four types of inheritance:

1. Single inheritance: a subclass inherits from a single superclass.

2. Multilevel inheritance: a subclass inherits from a superclass, which in turn inherits from another superclass.

3. Hierarchical inheritance: multiple subclasses inherit from a single superclass.

4. Multiple inheritance: a subclass inherits from multiple superclasses.

Java supports only single inheritance, which means that a class can only inherit from a single superclass. However, Java provides an alternative mechanism for achieving multiple inheritance through interfaces, which we will cover later in this article.

See also: How to Send Email using Gmail SMTP Server

Advantages of Inheritance in Java

Inheritance has several advantages in Java:

• Code reuse: Inheritance allows subclasses to use the methods and variables of their superclasses, which avoids duplicating code.

• Simplifies code maintenance: Inheritance creates a hierarchy of classes, which makes it easier to understand and modify code.

• Polymorphism: Inheritance allows subclasses to override methods of their superclasses, which enables polymorphism and flexibility in the code.

• Object-oriented design: Inheritance allows developers to model real-world relationships between objects, which is a key concept in OOP.

How to Implement Inheritance in Java

Inheritance is implemented using the extends keyword in Java. To create a subclass that inherits from a superclass, you simply use the extends keyword followed by the name of the superclass.

For example, the following code creates a subclass called Dog that inherits from a superclass called Animal:

class Animal {

  public void sleep() {

    System.out.println(“Sleeping…”);

  }

}

class Dog extends Animal {

  public void bark() {

    System.out.println(“Barking…”);

  }

}

In this example, the Dog class inherits the sleep() method from the Animal class, and adds its own bark() method. The Dog class is a subclass of the Animal class, and the Animal class is the superclass of the Dog class.

The Super Keyword in Java

The super keyword in Java is used to refer to the superclass of a subclass. It allows a subclass to call the constructor, methods, and variables of its superclass. 

The super keyword is used to avoid duplicating code, as it allows a subclass to reuse the functionality of its superclass.

There are three main uses of the super keyword in Java:

1. Call the constructor of the superclass

2. Call methods and variables of the superclass

3. Call the constructor of the superclass

When a subclass is created, it automatically calls the constructor of its superclass. However, if the superclass has parameters in its constructor, the subclass needs to explicitly call the constructor of the superclass using the super keyword. This is done using the following syntax: super(arguments)

The super() method should always be the first statement in the constructor of the subclass. For example, consider the following code:

class Animal {

  private String name;

  public Animal(String name) {

    this.name = name;

  }

}

class Dog extends Animal {

  private int age;

  public Dog(String name, int age) {

    super(name);

    this.age = age;

  }

}

In this example, the Animal class has a constructor that takes a name parameter, and the Dog class has a constructor that takes a name and age parameter. The Dog class calls the constructor of the Animal class using the super keyword with the name parameter.

The super keyword can also be used to call methods and variables of the superclass. This is done using the following syntax:

super.methodName();

super.variableName;

For example, consider the following code:

csharpCopy code

class Animal {

  private String name;

  public Animal(String name) {

    this.name = name;

  }

  public void sleep() {

    System.out.println(“Sleeping…”);

  }

}

class Dog extends Animal {

  private int age;

  public Dog(String name, int age) {

    super(name);

    this.age = age;

  }

  public void bark() {

    super.sleep();

    System.out.println(“Barking…”);

  }

}

In this example, the Dog class calls the sleep() method of the Animal class using the super keyword in its bark() method. This allows the Dog class to reuse the functionality of the sleep() method from its superclass.

The super keyword can also be used to access variables of the superclass. For example, consider the following code:

class Animal {

  protected String name;

  public Animal(String name) {

    this.name = name;

  }

}

class Dog extends Animal {

  private int age;

  public Dog(String name, int age) {

    super(name);

    this.age = age;

  }

  public void printName() {

    System.out.println(super.name);

  }

}

In this example, the Dog class accesses the name variable of the Animal class using the super keyword in its printName() method. The name variable is declared as protected in the Animal class, which allows subclasses to access it.

In conclusion, the super keyword in Java is a powerful tool that allows subclasses to call the constructor, methods, and variables of their superclass. It enables code reuse and avoids duplicating code, which is a key concept in object-oriented programming.

Method Overriding in Java

Method overriding is a concept in Java that allows a subclass to provide its own implementation of a method that is already defined in its superclass. 

When a subclass overrides a method, it provides a different implementation of the method that is specific to the subclass, but with the same method signature as the superclass method.

The main benefits of method overriding are code reuse and polymorphism. Method overriding allows a subclass to reuse the functionality of its superclass while also providing its own implementation that is specific to the subclass. 

This can result in more efficient and organized code, as well as easier maintenance and updates. Here is an example that demonstrates method overriding:

class Animal {

  public void eat() {

    System.out.println(“Animal is eating”);

  }

}

class Dog extends Animal {

  @Override

  public void eat() {

    System.out.println(“Dog is eating”);

  }

}

In this example, the Animal class has a method called eat() that prints “Animal is eating”. The Dog class extends the Animal class and overrides the eat() method with its own implementation that prints “Dog is eating”. 

The @Override annotation is used to indicate that the eat() method in the Dog class is intended to override the eat() method in the Animal class.

Now, consider the following code:

Animal animal = new Animal();

Dog dog = new Dog();

animal.eat(); // prints “Animal is eating”

dog.eat(); // prints “Dog is eating”

In this code, an instance of the Animal class and an instance of the Dog class are created. When the eat() method is called on the Animal instance, it prints “Animal is eating”. 

When the eat() method is called on the Dog instance, it prints “Dog is eating”. This demonstrates how method overriding can provide different behavior for the same method call depending on the specific type of the object.

Some key things to keep in mind when using method overriding in Java are:

• The overridden method must have the same method signature as the superclass method. This means that the method name, return type, and parameter types must be the same.

• The access level of the overridden method cannot be more restrictive than the access level of the superclass method. For example, if the superclass method is public, the overridden method must also be public.

• The overridden method can have a different implementation than the superclass method, but it cannot change the number or type of parameters or the return type of the method.

• The @Override annotation is optional but recommended. It can help to catch errors at compile time if the method signature in the subclass does not match the superclass method.

Final Keyword in Java

In Java, the final keyword is used to declare a constant or to indicate that a variable, method, or class cannot be modified or overridden.

Declaring a Constant:

When final is used to declare a constant, the value of the variable cannot be changed once it is initialized. Here’s an example: final int MAX_VALUE = 100;

In this example, MAX_VALUE is a constant with a value of 100. Once it is initialized, it cannot be changed.

Declaring a Variable:

When final is used to declare a variable, the value of the variable can only be assigned once. Here’s an example:

public void exampleMethod() {

   final int value = 10;

   value = 20; // This will result in a compile-time error

}

In this example, value is a variable that is initialized to 10 and then an attempt is made to re-assign it a value of 20, which results in a compile-time error.

Declaring a Method:

When final is used to declare a method, it indicates that the method cannot be overridden by any subclass. Here’s an example:

public class Animal {

   public final void speak() {

      System.out.println(“Animal is speaking”);

   }

}

public class Dog extends Animal {

   public void speak() { // This will result in a compile-time error

      System.out.println(“Dog is speaking”);

   }

}

In this example, the speak() method in the Animal class is declared as final, which means that it cannot be overridden by any subclass. When an attempt is made to override it in the Dog class, it results in a compile-time error.

Declaring a Class:

When final is used to declare a class, it indicates that the class cannot be subclassed. Here’s an example:

public final class MyFinalClass {

   // Class implementation here

}

In this example, MyFinalClass is declared as final, which means that it cannot be subclassed by any other class.

Some important things to keep in mind when using the final keyword in Java are:

• final variables must be initialized at the time of declaration.

• final methods cannot be overridden by any subclass.

• final classes cannot be subclassed by any other class.

• Using final can improve performance in some cases by allowing the Java compiler to optimize the code.

Abstract Classes in Java

In Java, an abstract class is a class that cannot be instantiated, meaning you cannot create an object of that class. Instead, it is meant to be a blueprint for other classes to inherit from, and it can contain both abstract and non-abstract methods.

To declare an abstract class in Java, the abstract keyword is used in the class declaration. Here’s an example:

public abstract class Shape {

   public abstract double getArea();

   public abstract double getPerimeter();

   public void print() {

      System.out.println(“This is a shape”);

   }

}

In this example, Shape is an abstract class that defines two abstract methods, getArea() and getPerimeter(). These methods do not have a body and are meant to be implemented by the classes that inherit from Shape. print() is a non-abstract method that provides a default implementation that can be inherited and overridden by the subclasses.

Subclasses that inherit from an abstract class must implement all of the abstract methods in the superclass. Here’s an example:

public class Circle extends Shape {

   private double radius;

   public Circle(double radius) {

      this.radius = radius;

   }

   public double getArea() {

      return Math.PI * radius * radius;

   }

   public double getPerimeter() {

      return 2 * Math.PI * radius;

   }

}

In this example, Circle is a subclass of Shape that implements the getArea() and getPerimeter() methods. It provides its own implementation for these methods because they were declared as abstract in the Shape class.

In addition to abstract methods, an abstract class can also have non-abstract methods that provide a default implementation. These methods can be inherited and overridden by the subclasses, just like any other non-abstract method.

Some important things to keep in mind when using abstract classes in Java are:

• An abstract class cannot be instantiated.

• Abstract methods in an abstract class do not have a body and must be implemented by the subclasses.

• Non-abstract methods in an abstract class can be inherited and overridden by the subclasses.

• Abstract classes can be used to provide a common implementation for a group of related classes.

Interfaces in Java

In Java, an interface is a collection of abstract methods that can be implemented by any class. It provides a way to define a contract that a class must follow without specifying the implementation details. Interfaces can also contain constants and default methods.

To declare an interface in Java, the interface keyword is used. Here’s an example:

public interface Animal {

   public void speak();

   public void eat();

   public static final String TYPE = “Animal”;

}

In this example, Animal is an interface that defines two abstract methods, speak() and eat(). These methods do not have a body and must be implemented by any class that implements the Animal interface. The interface also defines a constant TYPE that can be accessed by any class that implements the interface.

A class can implement one or more interfaces by using the implements keyword. Here’s an example:

public class Dog implements Animal {

   public void speak() {

      System.out.println(“Woof!”);

   }

   public void eat() {

      System.out.println(“Dog is eating.”);

   }

}

In this example, Dog is a class that implements the Animal interface. It provides its own implementation of the speak() and eat() methods, which were defined as abstract methods in the Animal interface.

An interface can also contain default methods, which provide a default implementation for the method. Here’s an example:

public interface Animal {

   public void speak();

   public void eat();

   public default void sleep() {

      System.out.println(“Animal is sleeping.”);

   }

}

In this example, the Animal interface contains a default method sleep(). A class that implements the Animal interface can use this default implementation or provide its own implementation.

Some important things to keep in mind when using interfaces in Java are:

• An interface can contain only abstract methods, constants, and default methods.

• A class can implement multiple interfaces.

• A class that implements an interface must implement all of its abstract methods.

• A default method in an interface can be overridden by a class that implements the interface.

• An interface can be used to provide a common interface for unrelated classes.

Differences Between Abstract Classes and Interfaces

Abstract classes and interfaces are both important concepts in Java that allow developers to create flexible and modular designs. However, they have some differences that are worth considering when choosing which one to use.

Here are some of the key differences between abstract classes and interfaces in Java:

1. Instantiation: An abstract class cannot be instantiated directly, whereas an interface cannot be instantiated at all.

2. Method implementation: An abstract class can have abstract and non-abstract methods, whereas an interface can only have abstract methods. Abstract methods do not have an implementation in the abstract class or interface, so they must be implemented by subclasses that inherit from the abstract class or implement the interface.

3. Multiple inheritance: A class can only extend one abstract class, whereas it can implement multiple interfaces. This means that interfaces provide greater flexibility in terms of multiple inheritance than abstract classes.

4. Accessibility: An abstract class can have different levels of accessibility for its members (methods and fields), whereas all members of an interface are public by default.

5. Fields: An abstract class can have instance variables and static variables, whereas an interface can only have constant fields (public static final) and cannot have instance variables.

6. Default methods: An interface can have default methods, which provide a default implementation for a method that a class implementing the interface can override if needed. An abstract class cannot have default methods.

7. Extensibility: An abstract class is more extensible than an interface. If a new method is added to an interface, all implementing classes must be updated to provide an implementation for the new method. In contrast, adding a new method to an abstract class does not require updating all subclasses.

When to use an abstract class:

• When you want to provide a base implementation for your subclasses.

• When you want to share code between related classes.

• When you want to enforce the implementation of a set of methods in subclasses.

When to use an interface:

• When you want to define a contract that unrelated classes can follow.

• When you want to provide multiple inheritance.

• When you want to provide a common interface for a group of unrelated classes.

In conclusion, abstract classes and interfaces both have their own strengths and weaknesses. Understanding the differences between them can help you choose the right one for your needs and create more flexible and modular designs.

Originally posted on May 9, 2023 @ 8:55 pm

Leave a Reply