How to override a method in Java – 030

In the last video we talked about how we can
create child classes from a parent class. This means we can create new classes that
have all the functionality of the parent class. One thing I mentioned, but glossed over, was
the fact that the child class can define new behavior for an existing method. We created a clock class with subclasses.
Each child class had their own way of telling time, even though each class used the same
method getTime(). Well it’s time we talked about how exactly we do that. In this lesson
I’ll show you how to override behavior for existing methods, how to stop another developer
from overriding your method, and we’ll look at some unintended consequences when you override
a method in Java. When we want to replace or modify functionality
in our child class methods, we override the method. In our clock example we are telling
Java, “hey when we call getTime(), we want you to use this new method instead of the
one in the parent class”. When Java goes to run the getTime() method, it will first look
in the current class. If it’s there, it will run it. So how do we override a method in
Java? We do this by marking the method with the
@Override annotation, and providing new functionality. We won’t go into annotations too much for
now, that’s a whole group of videos coming soon enough, but for now just know an annotation
in Java is a metadata hint for the compiler. If you forget to add the annotation for an
overridden method, Java will give you a warning. It’s not a big deal, but you want to get into
the habit of adding it. When we run the code in a main method like
this, “child method” is printed to the screen. We can even change the child variable to be
typed as ParentClass. The instance is still typed ChildClass. That means when we call
myPrintMethod(), we get the instance version of myPrintMethod() from the ChildClass. If we wanted to run the parent method first
as part of the child method, we use a special keyword called super. That looks like this. In this code, we’ll run the ParentClass
version of myPrintMethod() first, then we’ll continue with the implementation of myPrintMethod()
in the child class. That prints “parent method” and then “child method”. So in our digital clock let’s override getTime().
We provide a new method in the DigitalClock class and mark it with the annotation. The
signature of this method must match the signature in the parent method. Java will complain about
that too if they are different. We should also add a comment for this method.
Best practice says we should start the comment with the phrase “this implementation does
x” where x is what is different. There are two reasons you want to do this. One, as we’ve
seen, the annotation is optional. The original developer might forget it, so you want make
sure it’s clear this is an overridden method. And second it tells us exactly what is different
from the parent method. Our completed class will look like this. What happens when we don’t want a user to
override a method in Java. There might be a good reason why our implementation should
be the final version. That’s the keyword we need here. Final. When we mark a method as
final, that means we’re done. We cannot override a final method. If we don’t want child classes at all, we
can also mark the class as final. That means nothing can be overridden. The final on the
method isn’t needed. Everything is final and locked down in this case. This really
should be our starting point for designing classes. The reasons are similar to the arguments
we saw in the last lesson, why start with everything private. Best practice is we don’t
expose inheritance unless we intend the class to have child classes. And if that’s what
we want, selectively allow the methods we want overridden. Mark the rest as final. The last bit to cover here is something we
need to be aware of when making child classes. It’s called shadowing. Shadowing is when we
use the same variable name that overlap in scope. Say we have a protected variable in
the parent class called numberOfSeconds. Then in the child class we create another variable
and give it the same name, numberOfSeconds. This might seem like a contrived example,
but imagine the child class is written by a different developer. We’ll set the first variable to the value
24. And the second one to 42. Let’s add a method to the child class called toString()
which returns the value number of seconds as a string. Since toString is in Object,
we’ll override the behavior. Now let’s create the child class, and assign
it to the parent class. This is something we’ll do quite often in Java. Create a class,
but use the child implementation. Now if we set the value to something else, like 50.
What happens when we print the variable and then call toString()? We get 42 and 50. The parent variable is shadowed
by the child variable. We have to cast our class to the parent class in order to print
42. That’s one solution, but we know better. From the last lesson, we know the attributes
should be private. That means we can access them only through getters and setters. Using
a getter, we’ll always get the parent version 24. The child class will not know it’s shadowed
the parent variable since it’s private. If we want to override that behavior, we can
override the getter. Either way, by being explicit with the getters and setters, we
won’t get any surprised from accidental shadowing. And that’s the end of this lesson and how
we override a method in Java. We’ll look at another important object oriented concept
called polymorphism in the next video. If you have any questions about this video, leave
them in the comments below. And I’ll see you in the next video. Hey! Thanks for watching the video. If you
like what you’re seeing or have any questions, let me know in the comments or on!
New videos come out each week, so make sure you subscribe. You don’t want to miss a video!
In fact, lets go watch another DeegeU video. See you there!

Leave a Reply

Your email address will not be published. Required fields are marked *