Java Inheritance and Polymorphism: Concepts and Examples
Java Inheritance and Polymorphism
Multilevel Inheritance
Multilevel inheritance in Java occurs when a class is derived from a class that is also derived from another class, creating a chain of inheritance.
Example:
class Animal {
public void eat() {
System.out.println("Animal is eating");
}
}
class Dog extends Animal {
public void bark() {
System.out.println("Dog is barking");
}
}
class GoldenRetriever extends Dog {
public void fetch() {
System.out.println("Golden Retriever is fetching");
}
}
public class MultilevelInheritanceExample {
public static void main(String[] args) {
GoldenRetriever retriever = new GoldenRetriever();
retriever.eat();
retriever.bark();
retriever.fetch();
}
}
Method Overriding
Method Overriding: In Java, method overriding occurs when a subclass provides its own implementation for a method that is inherited from its superclass.
The overridden method in the subclass must have the same name, return type, and parameter list as the method in the superclass.
When an object of a subclass is used to call the overridden method, the subclass’s implementation is executed, not the superclass’s implementation.
Example:
class Animal {
public void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Dog barks");
}
}
public class MethodOverridingExample {
public static void main(String[] args) {
Animal animal = new Dog();
animal.makeSound();
}
}
Multiple Inheritance with Interfaces
Multiple Inheritance: Multiple inheritance is the ability of a class to inherit from multiple parent classes. While Java directly supports single inheritance, it allows for multiple inheritance indirectly through interfaces.
Interfaces: An interface is a reference type that defines a contract of methods that a class must implement. Interfaces contain only method declarations (no method bodies). A class can implement multiple interfaces, effectively inheriting the behavior defined in those interfaces.
Achieving Multiple Inheritance with Interfaces:
- Define Interfaces: Create multiple interfaces that define the desired behavior or methods.
- Implement Interfaces: Have a class implement all the desired interfaces.
- Override Methods: The class must provide implementations for all the methods declared in the interfaces.
Example:
interface Drawable {
void draw();
}
interface Shape {
void getArea();
}
class Circle implements Drawable, Shape {
public void draw() {
System.out.println("Drawing a circle");
}
public void getArea() {
// Implementation for calculating circle area
}
}
Single-Level Inheritance
Single-level Inheritance: In Java, single-level inheritance occurs when one class directly inherits properties and methods from another class. This creates a hierarchical relationship between the two classes. The class that inherits is called the subclass or derived class, and the class from which it inherits is called the superclass or parent class.
Example:
class Animal {
public void eat() {
System.out.println("Animal is eating");
}
}
class Dog extends Animal {
public void bark() {
System.out.println("Dog is barking");
}
}
public class SingleLevelInheritanceExample {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
dog.bark();
}
}
Abstract Classes and Methods
Abstract Class: An abstract class is a class that cannot be instantiated directly. It serves as a blueprint for other classes, defining common properties and methods that subclasses can inherit and implement. Abstract classes can contain both abstract methods and concrete methods.
Abstract Method: An abstract method is a method declared without a body. It is prefixed with the abstract
keyword. Subclasses of an abstract class must provide concrete implementations for all inherited abstract methods.
Example:
abstract class Animal {
public abstract void makeSound();
public void eat() {
System.out.println("Eating...");
}
}
class Dog extends Animal {
public void makeSound() {
System.out.println("Woof!");
}
}
class Cat extends Animal {
public void makeSound() {
System.out.println("Meow!");
}
}
The super
Keyword
The super
keyword in Java is used to refer to the superclass (parent class) of a subclass. It has several important uses in inheritance:
- Calling Superclass Constructor: To call the superclass’s constructor from a subclass’s constructor, use the
super()
keyword. This must be the first statement in the subclass’s constructor. If you don’t explicitly call the superclass’s constructor, the default no-argument constructor is called implicitly.
Example:
class Parent {
Parent() {
System.out.println("Parent constructor");
}
}
class Child extends Parent {
Child() {
super(); // Calls the Parent constructor
System.out.println("Child constructor");
}
}
- Accessing Superclass Members: To access a superclass’s instance variable or method from within a subclass, use the
super
keyword followed by a dot. This is especially useful when a subclass overrides a method and needs to call the superclass’s implementation.
Example:
class Shape {
int sides;
Shape(int sides) {
this.sides = sides;
}
public void getSides() {
System.out.println("Number of sides: " + sides);
}
}
class Rectangle extends Shape {
Rectangle(int sides) {
super(sides);
}
public void getArea() {
System.out.println("Area of rectangle: " + (sides * sides));
}
}
- Overriding Methods: When a subclass overrides a method from its superclass, it can use the
super
keyword to call the superclass’s implementation within its own method.
Example:
class Animal {
public void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
super.makeSound();
System.out.println("Dog barks");
}
}
Interfaces
Interface: In Java, an interface is a reference type that defines a contract of methods that a class must implement. Interfaces contain only method declarations (no method bodies). They are used to define a common behavior or contract that can be reused by multiple classes.
Need for Interfaces:
- Multiple Inheritance: While Java doesn’t directly support multiple inheritance for classes, interfaces allow a class to inherit behavior from multiple sources.
- Polymorphism: Interfaces enable polymorphism, where objects of different classes that implement the same interface can be treated as objects of that interface.
- Contract-Based Programming: Interfaces define a contract that classes must adhere to, promoting loose coupling and modularity.
- Abstraction: Interfaces provide a level of abstraction, separating the interface from the implementation.
Syntax:
interface InterfaceName {
// Method declarations
void method1();
void method2();
// ...
}
Implementation:
class MyClass implements InterfaceName {
public void method1() {
// Implementation of method1
}
public void method2() {
// Implementation of method2
}
}
Inheritance and Polymorphism
Inheritance: Inheritance is a mechanism in object-oriented programming where one class (subclass or derived class) acquires the properties and behaviors of another class (superclass or base class). This allows for code reuse and the creation of hierarchical relationships between classes.
Types:
- Single inheritance: A subclass inherits from only one superclass.
- Multiple inheritance: A subclass inherits from multiple superclasses.
- Multilevel inheritance: A subclass inherits from another subclass, which in turn inherits from a superclass.
- Hierarchical inheritance: Multiple subclasses inherit from the same superclass.
Polymorphism: Polymorphism means “many forms.” It allows objects of different classes to be treated as if they were objects of the same class. This can be achieved through:
- Method overriding: When a subclass provides a different implementation of a method inherited from its superclass.
- Method overloading: When a class has multiple methods with the same name but different parameters.
Example:
class Animal {
void makeSound() {
System.out.println("Generic animal sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Woof!");
}
}
class Cat extends Animal {
@Override
void makeSound() {
System.out.println("Meow!");
}
}
public class InheritanceAndPolymorphismDemo {
public static void main(String[] args) {
Animal[] animals = {new Dog(), new Cat()};
for (Animal animal : animals) {
animal.makeSound();
}
}
}
Nesting of Interfaces
Nesting of interfaces in Java allows you to define an interface within another interface. This can be useful for organizing related concepts and providing a more structured way to define functionality.
Why Nest Interfaces?
- Encapsulation: By nesting an interface within another, you can logically group related functionalities, improving code readability and maintainability.
- Modularity: Nesting can help create more modular and reusable code, as nested interfaces can be used independently or together.
- Clarity: Nesting can enhance code clarity by making the relationships between different concepts more explicit.
Syntax:
interface OuterInterface {
// Methods of OuterInterface
interface NestedInterface {
// Methods of NestedInterface
}
}
Example:
interface Drawable {
void draw();
interface Fillable {
void fill(Color color);
}
}
class Circle implements Drawable, Drawable.Fillable {
// Implementation of draw() and fill() methods
}
Single and Multilevel Inheritance
Single Inheritance: In single inheritance, a class can inherit properties and methods from only one direct parent class.
Example:
class Animal {
void makeSound() {
System.out.println("Generic animal sound");
}
}
class Dog extends Animal {
void bark() {
System.out.println("Woof!");
}
}
Multilevel Inheritance: In multilevel inheritance, a class can inherit from another class that itself inherits from a parent class. This forms a chain of inheritance.
Example:
class Vehicle {
void start() {
System.out.println("Vehicle started");
}
}
class Car extends Vehicle {
void drive() {
System.out.println("Car driving");
}
}
class SportsCar extends Car {
void race() {
System.out.println("Sports car racing");
}
}
Use of Interfaces in MLI: Interfaces define a contract of methods that a class must implement. They allow for multiple inheritance in Java, even though direct multiple inheritance is not supported.
MLI with Interfaces:
interface Drawable {
void draw();
}
interface Fillable {
void fill(Color color);
}
class Shape implements Drawable, Fillable {
// Implementations of draw() and fill()
}
class Circle extends Shape {
// Specific implementation of draw() and fill() for a circle
}