Java provides two mechanisms to achieve abstraction: abstract classes and interfaces. Both have their unique features and use cases.
1. Abstract Class
- Definition: An abstract class is a class that cannot be instantiated and is meant to be extended. It can have both abstract methods (without a body) and concrete methods (with a body).
- Features:
- Can have both abstract and non-abstract methods.
- Can have constructors.
- Can have instance variables and static methods.
- Supports single inheritance.
Example: Abstract Class
abstract class Animal {
String name;
// Abstract method
abstract void sound();
// Concrete method
void eat() {
System.out.println(name + " is eating.");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks.");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.name = "Buddy";
dog.eat();
dog.sound();
}
}
2. Interface
- Definition: An interface is a blueprint of a class that contains only abstract methods (prior to Java 8) and constants. From Java 8 onwards, interfaces can have default and static methods.
- Features:
- Cannot have constructors or instance variables.
- Can only have public, static, and final fields (constants).
- Supports multiple inheritance.
- Methods are
public abstractby default.
Example: Interface
interface Animal {
void sound();
default void eat() {
System.out.println("Animal is eating.");
}
}
class Dog implements Animal {
@Override
public void sound() {
System.out.println("Dog barks.");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.sound();
dog.eat();
}
}
Key Differences Between Abstract Class and Interface
| Feature | Abstract Class | Interface |
|---|---|---|
| Definition | A class with abstract and concrete methods. | A blueprint containing abstract methods and constants. |
| Constructors | Can have constructors. | Cannot have constructors. |
| Instance Variables | Can have instance variables. | Cannot have instance variables. |
| Inheritance | Supports single inheritance. | Supports multiple inheritance. |
| Access Modifiers | Can have any access modifier for methods and variables. | Methods are public abstract by default. |
| Default Methods | Not applicable. | Supported (from Java 8). |
| Static Methods | Allowed. | Allowed (from Java 8). |
| Fields | Can have fields of any type. | Only public static final constants. |
| When to Use | When a base class needs to share behavior. | When multiple unrelated classes need to share behavior. |
Use Cases
When to Use Abstract Class:
- When you need to share code between multiple related classes.
- When the class hierarchy requires a base class.
- When constructors or non-final fields are required.
When to Use Interface:
- When multiple unrelated classes need to share behavior.
- To achieve multiple inheritance.
- To define a contract for behavior without implementation.
Example: Abstract Class and Interface Together
abstract class Vehicle {
abstract void start();
void stop() {
System.out.println("Vehicle stopped.");
}
}
interface Electric {
void charge();
}
class ElectricCar extends Vehicle implements Electric {
@Override
void start() {
System.out.println("Electric car started.");
}
@Override
public void charge() {
System.out.println("Electric car is charging.");
}
}
public class Main {
public static void main(String[] args) {
ElectricCar car = new ElectricCar();
car.start();
car.charge();
car.stop();
}
}
Types of Inheritance in Java
Inheritance is a key feature of Object-Oriented Programming that allows a class (child or subclass) to inherit properties and methods from another class (parent or superclass). Java supports several types of inheritance.
1. Single Inheritance
- A class inherits from one superclass.
- Enables code reuse and extension of functionality.
Example:
class Parent {
void display() {
System.out.println("This is the parent class");
}
}
class Child extends Parent {
void show() {
System.out.println("This is the child class");
}
}
public class SingleInheritance {
public static void main(String[] args) {
Child child = new Child();
child.display(); // Inherited from Parent
child.show();
}
}
Output:
This is the parent class This is the child class
2. Multilevel Inheritance
- A class inherits from a subclass, creating a chain of inheritance.
Example:
class Grandparent {
void greet() {
System.out.println("Hello from Grandparent");
}
}
class Parent extends Grandparent {
void display() {
System.out.println("Hello from Parent");
}
}
class Child extends Parent {
void show() {
System.out.println("Hello from Child");
}
}
public class MultilevelInheritance {
public static void main(String[] args) {
Child child = new Child();
child.greet(); // Inherited from Grandparent
child.display(); // Inherited from Parent
child.show();
}
}
Output:
Hello from Grandparent Hello from Parent Hello from Child
3. Hierarchical Inheritance
- Multiple classes inherit from the same superclass.
Example:
class Parent {
void display() {
System.out.println("This is the parent class");
}
}
class Child1 extends Parent {
void show1() {
System.out.println("This is the first child class");
}
}
class Child2 extends Parent {
void show2() {
System.out.println("This is the second child class");
}
}
public class HierarchicalInheritance {
public static void main(String[] args) {
Child1 child1 = new Child1();
child1.display();
child1.show1();
Child2 child2 = new Child2();
child2.display();
child2.show2();
}
}
Output:
This is the parent class This is the first child class This is the parent class This is the second child class
4. Multiple Inheritance (Using Interfaces)
- Java does not support multiple inheritance with classes to avoid ambiguity (e.g., the diamond problem).
- However, it supports multiple inheritance through interfaces.
Example:
interface A {
void methodA();
}
interface B {
void methodB();
}
class Child implements A, B {
public void methodA() {
System.out.println("Method from Interface A");
}
public void methodB() {
System.out.println("Method from Interface B");
}
}
public class MultipleInheritance {
public static void main(String[] args) {
Child child = new Child();
child.methodA();
child.methodB();
}
}
Output:
Method from Interface A Method from Interface B
5. Hybrid Inheritance (Supported Through Interfaces)
- A combination of two or more types of inheritance.
- In Java, it is achieved using interfaces, as multiple inheritance with classes is not allowed.
Example:
interface A {
void methodA();
}
interface B extends A {
void methodB();
}
class Child implements B {
public void methodA() {
System.out.println("Method from Interface A");
}
public void methodB() {
System.out.println("Method from Interface B");
}
}
public class HybridInheritance {
public static void main(String[] args) {
Child child = new Child();
child.methodA();
child.methodB();
}
}
Output:
Method from Interface A Method from Interface B
Summary of Types
| Type | Description | Supported in Java |
|---|---|---|
| Single Inheritance | A class inherits from one superclass. | Yes |
| Multilevel Inheritance | A class inherits from a subclass, forming a chain. | Yes |
| Hierarchical Inheritance | Multiple classes inherit from the same superclass. | Yes |
| Multiple Inheritance | A class implements multiple interfaces. | Yes (via interfaces) |
| Hybrid Inheritance | Combination of multiple and other inheritance types. | Yes (via interfaces) |
By understanding these types of inheritance, you can design reusable, modular, and efficient object-oriented programs in Java.
Conclusion
- Use abstract classes when a base class is needed with shared behavior.
- Use interfaces to define common behavior across unrelated classes or achieve multiple inheritance.
- From Java 8 onwards, interfaces provide more flexibility with default and static methods, reducing the need for abstract classes in certain scenarios.