1. Introduction to Method Overriding and Recursion
In the previous chapter, we explored how to process collections efficiently using iterators and streams. Now, we shift our focus to a fundamental aspect of object-oriented programming - custom methods.
2. Defining a base class
Before diving into method overriding, let’s define a base class. This `Animal` class contains a simple method, `.makeSound()`, which prints `Animal sound`. Subclasses will later modify this behavior. The main method creates an `Animal` object and calls `makeSound()` to demonstrate its default behavior which is printing the line `Animal Sound`.
3. Understanding inheritance-extends
Inheritance allows a class to reuse another class’s properties and behaviors. Here, the `Dog` class inherits from `Animal` using `extends`, gaining access to `.makeSound()`.
Note that we don't need to import anything before using `extends`.
It also introduces its own `.bark()` method. The sample usage demonstrates how both inherited and unique methods function in a subclass.
In this example, it will print the `Animal sound` and `Bark` on separate lines.
This implementation is not particularly useful, but what if we could modify the behavior of `makeSound()` within the subclass to `bark` rather than returning a generic animal sound?
4. Overriding methods in Java
Overriding allows a subclass to change inherited behavior while keeping the same method signature. The `Cat` class now modifies `.makeSound()` to print `Meow` instead. The `@Override` annotation ensures correctness and prevents mistakes.
We don't need to import anything before using the `@Override` annotation.
The sample usage confirms that the new method replaces the inherited one and will print `Meow` when the `.makeSound()` method is called by a `Cat` instance.
5. Understanding recursion
`Recursion` is a technique where a method calls itself to break down complex problems into smaller, manageable subproblems. It is useful in scenarios like `countdowns`.
The `countdown()` method prints numbers from `n` down to `1`. The base case occurs when the parameter is `0`, which stops the recursion to prevent an infinite loop. Each recursive call decrements `n` by `1`, ensuring termination.
6. Recursion sample usage
In this example, the `.countdown()` method prints numbers from `5` to `1`, when it reaches the base case `0`, the method stop calling itself and exit.
We got the output as `5 4 3 2 1`, each printed on a new line.
7. Summary
We covered method overriding, where subclasses modify inherited behavior using `@Override`.
Inheritance allows code reuse through `extends`, while `recursion` helps break down complex problems.
Always ensure a base case to prevent infinite recursion.
8. Let's practice!
Now, let’s apply these concepts in the exercises!