What is inheritance and why it is needed?
Inheritance is a fundamental concept in object-oriented programming that allows a new class to
inherit properties and behaviors (methods and fields)
from an existing class. This new class is referred to as the "child" or "subclass," while the original
class is known as the "parent" or "superclass."
Inheritance promotes code reusability, enables polymorphism, and establishes a hierarchy
between classes. It is essential for reducing code redundancy
and making code maintenance easier, as changes in the superclass are automatically reflected
in the subclass.
Types of Inheritance with Examples
1. Single Inheritance: A class inherits from one parent class only.
Example:
```java
class Parent {
void display() {
System.out.println("Parent class");
class Child extends Parent {
void show() {
System.out.println("Child class");
}
```
2. Multilevel Inheritance: A class inherits from a child class, forming a chain of inheritance.
Example:
```java
class Grandparent { }
class Parent extends Grandparent { }
class Child extends Parent { }
```
3. Hierarchical Inheritance: Multiple classes inherit from a single parent class.
Example:
```java
class Parent { }
class Child1 extends Parent { }
class Child2 extends Parent { }
```
4. Multiple Inheritance (via Interfaces in Java): A class can inherit from multiple interfaces.
Example:
```java
interface Interface1 { }
interface Interface2 { }
class Child implements Interface1, Interface2 { }
```
Why Multiple Inheritance through classes is not supported in Java?
Multiple inheritance through classes is not supported in Java to avoid the ambiguity caused by
the "Diamond Problem." The Diamond Problem occurs when a
class inherits from two classes that have a common base class, resulting in conflicts due to
potentially inherited duplicate methods or fields. Java
resolves this by allowing multiple inheritance only through interfaces, providing flexibility without
the risk of ambiguity.
Method Overriding with Example
Method overriding occurs when a subclass provides a specific implementation of a method that is
already defined in its superclass. This enables runtime
polymorphism, allowing the program to call the overridden method of the subclass.
Example:
```java
class Animal {
void sound() {
System.out.println("Animal sound");
class Dog extends Animal {
@Override
void sound() {
System.out.println("Bark");
```
Here, `sound()` method is overridden in `Dog` class, allowing it to have its own implementation.
Difference between Runtime and Compile-time Polymorphism
1. Compile-time Polymorphism:
- Also known as method overloading.
- The method to be called is determined at compile time.
- Achieved by having multiple methods with the same name but different parameters.
- Example: Method Overloading.
2. Runtime Polymorphism:
- Also known as method overriding.
- The method to be called is determined at runtime.
- Achieved through inheritance and method overriding.
- Example: Method Overriding as seen in subclasses.