Inheritance and method overriding are central concepts in object-oriented programming (OOP) that allow Java developers to promote code reuse, extensibility, and polymorphism. This discussion covers how methods are inherited and overridden when using superclass and subclass relationships in Java.
Inheriting Superclass Methods
- Definition:
- When a subclass is created using the extends keyword, it automatically inherits all non-private methods of the superclass.
- Access Rules:
- Public and Protected methods are inherited and accessible in the subclass.
- Private methods are not inherited directly but can be accessed indirectly through public/protected methods in the superclass.
- Default (Package-Private) methods are inherited only if the subclass is in the same package as the superclass.
- Usage:
- Subclasses can directly call inherited methods unless overridden.
Example:
class Parent {
void display() {
System.out.println(“This is a method from the parent class.”);
}
}
class Child extends Parent {
}
public class Main {
public static void main(String[] args) {
Child child = new Child();
child.display(); // Inherited method
}
}
Output:
This is a method from the parent class.
Overriding Superclass Methods
Method overriding occurs when a subclass provides a specific implementation of a method that is already defined in its superclass.
Rules for Overriding
- Method Signature:
- The overridden method in the subclass must have the same name, return type, and parameter list as the method in the superclass.
- Access Modifier:
- The access level of the overridden method in the subclass cannot be more restrictive than the superclass method.
- Example: If a superclass method is protected, the subclass method cannot be private.
- The access level of the overridden method in the subclass cannot be more restrictive than the superclass method.
- Annotations:
- It is good practice to use the @Override annotation for clarity and to avoid mistakes.
- Exception Handling:
- The overriding method cannot throw new or broader checked exceptions than the overridden method.
- final Methods:
- Methods declared as final in the superclass cannot be overridden.
- Static and Private Methods:
- Static methods cannot be overridden but can be re-declared (method hiding).
- Private methods are not visible to the subclass and hence cannot be overridden.
Example of Method Overriding
class Parent {
void display() {
System.out.println(“This is a method from the parent class.”);
}
}
class Child extends Parent {
@Override
void display() {
System.out.println(“This is a method from the child class.”);
}
}
public class Main {
public static void main(String[] args) {
Parent obj = new Child(); // Polymorphism
obj.display(); // Calls the overridden method in the subclass
}
}
Output:
This is a method from the child class.
Using the super Keyword
The super keyword allows a subclass to explicitly call the methods of its superclass. This is particularly useful when the subclass overrides a method but still wants to invoke the superclass implementation.
Example: Accessing Superclass Method
class Parent {
void display() {
System.out.println(“This is a method from the parent class.”);
}
}
class Child extends Parent {
@Override
void display() {
super.display(); // Call the parent class method
System.out.println(“This is a method from the child class.”);
}
}
public class Main {
public static void main(String[] args) {
Child child = new Child();
child.display();
}
}
Output:
This is a method from the parent class.
This is a method from the child class.
Polymorphism with Overridden Methods
Overridden methods play a critical role in runtime polymorphism. When a superclass reference points to a subclass object, the overridden method in the subclass is invoked.
Example: Runtime Polymorphism
class Parent {
void show() {
System.out.println(“Parent’s show method”);
}
}
class Child extends Parent {
@Override
void show() {
System.out.println(“Child’s show method”);
}
}
public class Main {
public static void main(String[] args) {
Parent obj = new Child(); // Upcasting
obj.show(); // Calls the child’s overridden method
}
}
Output:
Child’s show method
Overriding vs Method Hiding
- Instance Methods (Overriding):
- Instance methods are overridden, and the method that gets called depends on the runtime type of the object.
- Static Methods (Method Hiding):
- Static methods are not overridden but hidden.
- The method call is resolved at compile-time based on the reference type.
Example: Method Hiding
class Parent {
static void display() {
System.out.println(“Static method in parent class”);
}
}
class Child extends Parent {
static void display() {
System.out.println(“Static method in child class”);
}
}
public class Main {
public static void main(String[] args) {
Parent obj = new Child();
obj.display(); // Calls the static method of Parent class
}
}
Output:
Static method in parent class
Access Modifiers and Overriding
Superclass Modifier | Allowed Subclass Modifier |
public | public |
protected | protected or public |
default (package-private) | default, protected, or public (if in the same package) |
private | Not applicable (cannot override) |
Final Methods and Classes
- Final Method:
- Declared using final in the superclass.
- Cannot be overridden in the subclass.
Example:
class Parent {
final void display() {
System.out.println(“This is a final method.”);
}
}
class Child extends Parent {
// Compilation error if display() is overridden
}
- Final Class:
- A class declared as final cannot be extended.
Best Practices
- Always use the @Override annotation to ensure the method is correctly overriding a superclass method.
- Use the super keyword to reuse superclass functionality when overriding methods.
- Avoid overriding static methods; use different method names to avoid confusion.
Conclusion
Inheritance and overriding are powerful features in Java that enable code reuse and dynamic behavior through polymorphism. Proper understanding and implementation of these concepts allow for more flexible, maintainable, and efficient software designs.