TIL: Inheritance pt1
Coming off of the talk of constructors and variables, we’re going to move on to the concept of inheritance.
This is a topic that completely baffled me back when I took coding classes in school… of course that’s not really saying much as most of the classes had left me completely confused, but I digress. Inheritance isn’t that hard at all and it actually provides a huge amount of functionality to your code by using it. This is why it’s one of the main pillars of OOP.
What Is Inheritance?
Inheritance allows you to essentially build classes off of one another. You start with a base class and then continue to extend that functionality on with additional classes. Each of these new classes are denoting with an extends
modifier in their declaration, pointing back to the base class in which they’re expanding.
Each class is able to extend from exactly one class (you can’t stick a bunch of them in there). But that’s not to say that you can’t chain more than once! As we’ll see in an example below, there’s nothing preventing you from chaining multiple classes together.
The interesting thing to note here is that even if your class doesn’t explicitly extend another class, it will automagically extend the Object
class. This won’t be visible in your code, but it will be there. How can you tell? Well, the Object class comes with its own set of methods that are available to use right out of the box. Create a new class. Then try to call the .toString()
method. Surprise! You didn’t write it, but it’s available for you to use!
And that’s what inheritance is all about. As you continue to extend classes, you keep the abilities of the base class, but add more functionality on top of it. That means that any constructors, methods, or properties that existed in the base class will be available to use in the extended class.
Inheritance Example
Let’s start working through an example of this to get a better idea of what’s going on. I’m going to create a base class called Animal
which really has nothing more than a few properties and some getters and setters:
|
|
This is just a normal class. Nothing special going on here.
But now let’s say that I wanted to extend Animal to support a Dog
class. I could add in a few more parameters and maybe add few constructors:
|
|
Notice how the declaration says Dog extends Animal
. This is what will give us access to everything inside of the Animal
class. This means that we can call methods inside the Animal
class, like our setters and getters, just by calling their method name. See how we’re setting our values in dog?
Super and Override
By default, when you extend from a class you will be implicitly calling the empty constructor of the base class. Anything that’s set in that base class is going to be set when you initialize your new extended class.
But what if you want to specify a different constructor than the default empty set? That’s where super
comes in.
With super
you can actually specify specifically what you want to pass up to the base class constructor, allowing for different constructors to be hit. Let’s take a look a another super simple example:
|
|
In this case I’m just declaring another class and extending from Dog
this time (notice how this is the second extension of Animal
). Everything from the Animal
and Dog
classes (as well as Object
) are available to us.
Because I am making an object for an explicit type of dog, I already know what it’s breed is. Therefor I want to utilize the constructor that accepts the breed back in the Dog
class. To do so, I call super("Shiba-Inu")
.
But what if you need to modify some of the functionality of one of methods from a base class? That’s where the @Override
annotation comes in! You can preface your method declaration with an @Override
to allow for the functionality of that method to now be overridden with your new class.
Example time. Remember that in our initial declaration of the Animal
class, we had created a method called makeSound()
. Now that we know exactly what kind of breed of dog we’re talking about, we know exactly what sound it’s going to make. So let’s override that method with a new one for our Shiba:
|
|
It’s that easy!
…but what if you still want to access the original makeSound()
in another method? super
is back again to help us out!
|
|
By using super.makeSound()
we gain access back to the method even though we’re overriding it in this same class!
Wrap Up
Hopefully you found some of this helpful or interesting. There’s still some more topics that I need to cover with regards to inheritance that I hope to cover in tomorrow’s blog.
As always, the code from this post can be found over in my github repo.
💚 A.B.L.