TIL: Inheritance pt2
We’re going to continue where we left off yesterday and discuss a few more things related to inheritance.
Now that we have a good understanding of how inheritance works there’s a few more things to cover to round out our understanding.
When defining your class and methods, you have a variety of keywords available to tag onto definition. This typically would go in front of the type declaration. One of these keywords is
final do? It tells the compiler that either the class or the method cannot be extended or overwritten, respectively. This can be handy if you’re trying to lock down the class and prevent someone from using it outside of your defined purpose.
Let’s take the examples from the lessons yesterday. Let’s suppose I decide that I don’t want someone to be able to extend the
Dog class. I can lock this down by adding a
final to the class definition:
By adding the final to the entire class, our
Shiba class will no longer be able to extend
Dog and now starts to throw errors.
We can do the same thing with individual methods as well. Recall from before that we had defined our
Shiba class to
makeSound() method from the base
If I were to go into the base
Animal class and mark the
makeSound() method as
final, we’ll see that we get an error present in the
Shiba class for the @Override:
So just like you can prevent a class from being extended or class being overridden, you can also require that a class be extended or that a method be overridden. That’s where the
abstract keyword comes in.
abstract, there’s two rules to follow:
- If marking a method as
abstractyou must mark the class as
- If marking a class as
abstractyou DO NOT need to mark any methods as
Number two above is not very common, but it is possible to do.
Using our examples from before, we could change both our
Dog classes to be
abstract and our tests would still continue to pass. But what about methods?
When defining an
abstract method, you will need to define it without any body. You can define the name, the return types and the accepted parameters, but you cannot define any logic to it. This means that every class that inherits this method will need to define their own logic.
Let’s add in a new
abstract method into our base
Notice how there is no body (curly braces) in the definition. If you try to even put them in, even if they’re empty, you will get errors.
Now let’s write our method inside of the Dog class:
That will clean up all of errors and allows the method to be specific to the inherited class.
This is more of a “good to know” rather than directly related to the inheritance that we’ve been talking about.
As mentioned in yesterday’s post, everything inherits from the
Object class. Along with
Object comes the
equals() method. By default, this equals method will only validate whether two references point to the same object in memory.
That’s to say, if I were to create two different instances to two different
Dog objects and then see if they are equal, it would return false:
However, if we tweaked this a little bit and had b pointing to a, then this would be true:
@Override like we learned yesterday, we can actually change the
equals() method on a per class basis so that it does exactly what we want it to do. So instead of comparing whether or not it’s the exact same object, we could check to see if it’s two
Dog classes with the same breed or name or something like that.
That wraps up everything I wanted to talk about regarding inheritance. That should be a pretty good start to get you going. As always, the code from this lesson is available on my github page.