Picture this - you’re at a car dealership and you’re eager to purchase your first car. You settle on a brand new Honda Civic, and your representative asks: sedan or hatchback?
Some folks might consider making a venn diagram to compare and contrast a sedan with a hatchback. It might look something like this:
While there are a few differences between a sedan and a hatchback, these two types of cars are actually very similar. They perform many of the exact same functions in the exact same way. They have the same engine, same technological features, same safety measures, etc. If we were to restructure our conversation around code, we’d say that sedans and hatchbacks inherit many of the properties common to all cars. The car, in this context, will be our parent class.
Let’s implement a Civic parent class
The Car class has many useful methods that both sedans and hatchbacks need to use.
Now, let’s take a look at the sedan and hatchback classes:
Notice, in this example, we are implementing an override. This is because while Hatchbacks and Cars both can pop their trunks, they do it in slightly different ways. The trunk of your sedan will be its own storage area, whereas the hatchback will connect to the main interior of the car. It’s important to be careful when using overrides, as your method signatures and return types should be identical to your parent class. The override is an annotation that signals to the compiler that you are modifying code from the parent class.
Finally, let’s take a look at our main class
Notice that our sedan and hatchback instantiation declares both Sedan and Hatchback as a Civic. This is an example of polymorphism, or a way of coding generically that allows for the instances of related classes to be declared as a similar type. If we execute the code, we can see that the turnOn() method, which is declared in the civic parent class, will print equivalent statements for both types of cars despite the fact that Sedan and Hatchback are different subclasses. However, they have unique method declarations for their popTrunk() method, and will have their own print statements.
In this specific example, if you were to declare Sedan as "sedanCar = new Sedan()" this would not cause any issues, and the code would compile and execute the same. However, polymorphism allows for code to be extensible, as you can pass anything that is a civic as an instance to other methods. One way to demonstrate this principle would be implementing a driver class that has a move civic method. This person can have a drive method that accepts any type Civic as a parameter:
Below, we can pass in an instance of a hatchback into the useCar method, because a hatchback is a Civic.
Voila! The power of inheritance and polymorphism. A deep understanding of this concept is pivotal, but just one step in the vast journey of object-oriented programming.