13.3 Inheritance and Polymorphism in Java: Method Overriding
Inheritance is one of the fundamental pillars of Object Oriented Programming (OOP), allowing the creation of new classes based on existing classes. In Java, this is done with the extends
keyword. Inheritance promotes code reuse and the creation of a class hierarchy. Associated with inheritance, we have the concept of polymorphism, which, in its simplest form, can be understood as the ability of an object to be referenced in several ways.
Polymorphism manifests itself in two main ways in Java: method overloading and method overriding. In this section, we will focus on method overriding, which is a mechanism by which a subclass provides a specific implementation of a method that is already provided by one of its superclasses.
Understanding Method Overriding
Method overriding occurs when a subclass in Java redefines a method of the superclass. For a method to be overridden, it must have the same signature in the subclass and superclass, that is, the same name and the same parameters. Overriding is a powerful tool that allows a class to inherit methods from a parent class and still modify its behavior as needed.
Rules for Method Overriding
There are some important rules that must be followed to correctly override a method in Java:
- The method in the subclass must have the same name, return type (or subtype), and parameters as the method in the parent class.
- The visibility of the overridden method in the subclass cannot be more restrictive than the visibility of the method in the parent class.
- The overridden method cannot throw checked exceptions wider than those thrown by the parent class method.
- Methods marked as
final
cannot be overwritten. - Static methods are not overridden, but hidden, which is a different concept.
Method Overriding Example
Let's consider a simple example to illustrate method overriding:
class Animal {
public void emitSound() {
System.out.println("The animal makes a sound.");
}
}
class Dog extends Animal {
@Override
public void emitSound() {
System.out.println("The dog barks: Woof! Woof!");
}
}
In the example above, the Dog
class overrides the EmitSound
method of the Animal
class. When an object of type Dog
calls the emitSound
method, the overridden implementation is executed, causing it to print "The dog barks: Woof! Woof!" instead of "The animal makes a sound.".
Using the @Override Annotation
The @Override
annotation is used above the override method. Although it is not mandatory, it is good practice to use it because it tells the compiler that you intend to override a superclass method. If the corresponding method is not found in the superclass, the compiler generates an error, preventing possible typos or method signature errors.
Benefits of Method Overriding
Method overriding allows developers to create more flexible and reusable systems. It offers the following benefits:
- Specific Behavior: Subclasses can define specific behavior that is different from the behavior defined by the superclass.
- Polymorphism: The same method can have several different implementations, depending on the object being referenced.
- Simplified Code Maintenance: If a superclass method is modified, only the overrides that depend on the original implementation need to be changed.
Final Considerations
Method overriding is an essential feature in OOP and Java. It allows developers to create more specialized classes that behave appropriately while maintaining consistency and code reusability. By understanding and correctly applying method overriding, you can create robust, easily extensible systems.
Finally, it is important to remember that method overriding is just one aspect of polymorphism in Java. Other aspects, such as method overloading and interface implementation, also play a crucial role in creating complex and flexible applications. With practice and an understanding of these concepts, you will be well equipped to harness the power of OOP in your Java projects.