Abstract Classes Part 1

A free video tutorial from Tim Buchalka
Java Python Android and C# Expert Developer - 1.56M students
Rating: 4.5 out of 5Instructor rating
13 courses
1,572,167 students
Abstract Classes Part 1

Lecture description

Get to know more about Abstraction in this lecture.

Learn more from the full course

Java 17 Masterclass: Start Coding in 2024

Acquire Key Java Skills: From Basics to Advanced Programming and Certification - Start Your Dev Career

136:35:35 of on-demand video • Updated June 2024

Learn the core Java skills needed to apply for Java developer positions in just 14 hours.
Be able to sit for and pass the Oracle Java Certificate exam if you choose.
Be able to demonstrate your understanding of Java to future employers.
Learn industry "best practices" in Java software development from a professional Java developer who has worked in the language for close to 25 years.
Acquire essential java basics for transitioning to the Spring Framework, Java EE, Android development and more.
Obtain proficiency in Java 17, as well as older versions incluing Java 11 and Java 8.
Java 21 features coming soon!
So in this set of videos we're gonna start talking about Abstractions. So abstraction is when you define the required functionality for something without actually implementing the details. In other words we're focusing on what needs to be done, not on the how it's to be done. So, interface is, as you saw, are purely abstract, and they don't specify any actual aspect of the implementation. The actual implementation, of course, was left to the classes that implement the interface, and that's why we use the word implements when we're using an interface. And as you can see, I've got the challenge from the interfaces set of videos. And I'm just gonna go through and just confirm that again. So you can see that we've got our interface here. Now this was the interface that originally had the ArrayList. And if you remember I changed it back to a list, and I changed it back to ArrayList here just to actually talk about this a little bit more. But again, getting back to the interface, the interface defines what needs to be done. It doesn't define how it's done. The how, we actually have to go into the class. In this case say Monster, and that's actually implements that's implementing the Isavable interface meaning that it's actually gonna do the work. And we're getting that error right now by the way, because as you remember we actually changed this to a list. But I've purposely change the interface back to an ArrayList because I wanna talk about that. So the ISaveable interface, as you can see onscreen, provided, or specified that there must be a write method that returned an ArrayList of values to be saved, and also the read method. As you can see on the screen, there that was provided with an ArrayList of values to be restored. So there weren't any other details of how the class should populate, or write the ArrayList. No details on what the class should do with the read values either, that's left entirely up to each individual class. You could really if you wanted to, set it up so that each class implemented this interface might do completely different things with the write and read methods. There's no rules of what's to be done with those methods and interface. And that those methods have to be implemented in a particular class. But strictly speaking, if you look at this interface, it's not complete abstraction. And the reason is in this particular case, there's a specification that ArrayLists must be used. But in a typed language like Java it's hard to avoid doing that sometimes. But in this particular case, and I explained this a little bit in the challenge, in the previous challenge, the interface challenge, we can abstract this and use just a List. So what we could've done is we could've changed, and what we did do is we changed it, so we actually removed the need for an ArrayList, and actually just changed it so in actual fact it was just a list. And by doing that, we abstracted again, because we then didn't force the Monster class or the Player class or any other class that implemented this interface to have to use an ArrayList. They could use any type of list for that matter. And that can be really useful and I have made a recommendation that you should do that whenever you are using a list of some type in your programs. Generally speaking in terms of the declaration, it's good to write it like that and that leaves your implementation open to actually use any type of that is anything that implements that particular interface in which case this is the list interface which part of Java. And just as a recap, we can see that is if we actually click on this, I'm holding down command, I believe it's Alt on your control, sorry, on a Windows machine. Click on it, we can go into the actual list interface, which is part of Java, is quite interesting, actually reading some of the code sometimes. And you can see that this is actually the public interface for the list, which the other classes such as ArrayLists within Java etc., actually have to implement to actually use. Now obviously by definition, being an interface is abstract, so you can't use a new ISavable or a new list. What you need to do is instantiate a class that implements the interface. And you obviously saw that in the interface challenge. Now Java also allows abstract classes. Now, before we get too much into that, I just wanna go one step further and just mention that with this interface, we could've actually taken it one step further, because we specified the type to be string. But again, if we wanted to be really flexible, we could even remove that and made that a really generic list. And left that up to the user, the class that implemented this interface to actually decide what type to actually use. So I could have quite happily done that, and we could have then gone back to our monster class, and actually look to changing it, we would have to change a few little things around a little bit with terms of the definitions. But ultimately you could have given that extra functionality, or the extra flexibility I should say for the actual classes that we're implementing in this interface. So keep that in mind that you can take it one step further if you wanna go to that level and leave yourself maximum flexibility. But sometimes there's a bit of a fine line as to how generic you make it and how specific. Sometimes, somewhere just in the middle might be the way to go. So as I mentioned, interfaces are by definition, in Java, Abstract. So you can't use the new ISavable or new list. You have to, instantiate a class that interface, that implements I should say, the interface. And what I'm gonna do is I'm gonna close this one down now, I'm gonna swap over because I've created a new Project in IntelliJ for Abstraction. We are gonna actually start typing some code. Because as I mentioned, Java also allows abstract classes. And these are classes that define methods, but do not provide an implementation of those methods. The implementation itself is left to the classes that inherit from the abstract class. So this is different from inheriting from an interface. You can also inherit from an actual class as well. So in the videos in inheritance we created a very basic animal class, and then we extended it to create a dog. let's see if we can do something similar now, using an abstract class. So I'm going to actually open up this now and create a new class. New > Java class, and I'm going to call it Animal. And what I'm gonna do is I'm gonna make this an abstract class. So to do that we type in the word abstract after our modifiers. So, public abstract class Animal, and we can define the variable. So we just type private String name, we can have a constructor, which we'll pass us the name of the animal. And let's also add a couple of extra abstract methods, and this is the part I wanna show you for eating and breathing. So we can put public abstract, again the abstract keyword after the modifier, void, eat, and notice we've just put a semicolon there, so we haven't implemented this at all. And public abstract void breathe. And we can also add a constructor. Sorry, we can also add a getter I should say, to name. So there's an abstract class, and you can see here what we are doing is, as we're about to see, we're gonna inherit from this abstract class. And it's gonna let us define behaviors that are necessary, without specifying how they are to be performed. And this really ensures that the subclasses, such as the dog, must actually implement them, because of course, normally, in the normal class, if you're extending from a class, you can create a base method in the class. But there's no requirement for the other class, the class that is subclassing to actually implement those methods. But by creating abstract methods, we actually are forcing the class that is ultimately gonna implement from this abstract class to create those methods for us. And that's why we've actually marked them as abstract. The other methods and the other field in this case are quite okay, and they work as normal Java code. But we're actually specifying and saying there's some abstract methods here that have to be implemented. So if you did actually refer back to the inheritance videos, you'll see that this is very similar to that. Really the only difference is we've actually marked it as abstract, the actual class definition at the top there. And also we included those abstract methods as well. So to keep things simple in this example, I've actually removed the member variables like brain, weight, etc., just to keep things really simple. Now if we actually tried extend from this I wanna show you what actually happens. So I'm gonna create a new class, I'm gonna call it Dog. I'm gonna extends Animal. And I think I've put Animal in the wrong place, Animal should have been in that package, so I'm just gonna move that. Drag it and it's asking where I want to move it to? I want to move it to that package, so I'm gonna click on Refactor. And that should fix it up now, so we're actually in the right place. But now you can see we've got a different type of error. And if we have a look at that, it's actually telling us that class dog must either be declared abstract or it needs to implement the abstract method eat in animal. And in actual fact there was two methods there that needed there to implement, but this little error message is only popping up the first one. So you can see that now, in order to be able to create a valid class, we have to implement those methods. So we can do something like create a constructor first, the Dog like so, and we'll just use the default super to save the actual name, which is in the animal class. And we can do some overrides now. So we can do Alt+N and we can actually go to implement or override, they'll both actually pop up the same things. And you can see now we've got two options here. We've got the two options there and notice the little descriptions here or the little icons, they were a little bit different. So getName you can see that's like a method, but this one is also a method. But notice how it's got a chunk taken out of it. That's IntelliJ way of telling you that this is an abstract method. So I can actually select both of those and override them, which then makes the class valid and I can just put something in the code. GetName + is eating. And for breath, Breath in, breath out, repeat, pretty basic. So that's now made it a valid class as you can see. And also keep in mind that, because we did implement the getter for the name, getName in the Animal class it's available in this class when I actually used it here in the eat method. And likewise from the constructor I mentioned that we actually called, the constructor using the super keyword, which calls the constructor that's actually in the animal class as well. So the important thing here is that not all methods have to be abstract. This is one of the differences between an abstract class and an interface, you can actually mix these up. An interface, if you recall, if you go back and have a look. Actually it looks like I closed the project, I probably should have just switched over. But with the previous interface which you saw earlier in the video, the entire interface was completely abstract, and there's no implementation whatsoever. So there's no opportunity for us to enter fields. There wasn't any opportunity for us to enter any other code. We purely were able just to specify the methods that were gonna be used for that interface, that a class that was implementing that particular interface had to actually fulfil in order to make it valid. But as you can see in the case of Animal, we can actually mix it up. We can actually add fields. We can add regular methods, or a constructor in this case. But also a regular method as you can see there with the constructor. But then we can also specify that certain methods are abstract as you can see there. So in terms of actually using this, it works now as you would expect. So if you go to write some code, we could do something like Dog _dog = new Dog, Yorkie, dog.Breathe. Again, it behave, you would think it would work, dog.eat. And if I actually run that. Breathe in, breathe out, repeat. Yorkie is eating, so you can see that it's all working nicely, as you would think that it would be. Okay, so that's working as you think it would but let's take this now to the next step and actually create another class, which in this case is going to be bird. New > Java class, and we're gonna call that Bird. Bird and we need to extend, cuz like obviously, using the extends keyword, because it's a class, and Animal. And create a constructor, which works as you think it would, and let's also override those methods. Eat and Breathe, again. And we'll put for eating, getName + is pecking. And for breathing, well, it's going to be the same, so it's breathe in, breathe out, repeat. Like so, and of course, we can then go back to our main class, main method. Bird, bird = new Bird. Bird.breathe. Bird.eat. You can run that. We get the results, as you can see. Birds breathing, and parrot is pecking, Yorkie's eating. So it's doing the right thing there. Now birds can also fly, so it could be a good idea to add a fly method to our bird class. But, not all birds can fly, so implementing a fly method in the bird class is not a good idea. Better idea would be to create an abstract Bird class that extends Animal, and also has an abstract fly method that individual Bird objects can implement as they're able to. So let's go ahead and see how that would work. So we'll go through now and modify our Bird class. Close this down to give us a bit of space. Now I'm gonna change this up here, now where we had public class Bird, I'm gonna make that abstract. Leave the constructor as it was and also leave the two methods as they were, but also down the bottom, let's add another abstract method. So public abstract void fly. So that's another abstract class at this point. So this is an abstract class that itself is extending from another abstract class. It's implementing the required methods that the Animal class requires it to, namely eat and breathe. But it's also defining an abstract method fly. That ultimately has to be overridden by another class as well. And of course we made this class abstract, which it needs to be in order to do this anyway. So now that we've done that, of course we go back to the main class we'll get an error because, hold on so we can see what the error is. So Bird is abstract. It cannot be instantiated. Remember, we said that earlier in the video, that you can't directly instantiate a class that is abstract in anyway. So what we need to do is actually create another class. So to do that, we'll change this, and we'll actually create a Parrot class. Back here, and create a new class, Parrot. We can extend, extends Bird, without a constructor. And all we need to do here, is because the other methods are already overridden in the Bird class, we only really need to do one. So if we go back there and have a look, and go to override, we can still override Eat and Breath if we wanted to, if for some reason this type of bird had a different way of eating or breathing. But really, all we wanna do is override fly in this case, to make this class valid. So I'm gonna do that, and I'm gonna put something like Flitting from branch to branch. So it's actually flying effectively from branch to branch. And again parrots automatically inheriting eat and breath from the, and breath, I should say from bird, so we don't have to re implement those methods again. It now has its own implementation for fly. So if you go back to the main method now. We'll now change this so this is actually parrot, instead of a bird. Remembering that Parrot is now extending from Bird. Parrot set to new Parrot, and now instead of typing Parrot as a name, we'll say it's an Australian ringneck, and it's gonna be Parrot.breathe. That will still work. Parrot.eat. But we're also gonna do parrot.fly now. So if you run that, you can see that there's no errors anymore. You can see now Australian ringneck is pecking, flitting from branch to branch. And just as another example to show that we can do something different, let's create one more class. New > Java Class and we'll call this one Penguin. And we got to extend from Bird again, extends from bird. Create a constructor. And let's just override fly again. And we can put I'm not very good at that. Can I go for a swim instead. And that's our implementation of penguin. So going back to the main method again, we can just come down here I can put Penguin, penguin = new Penguin, Emperor and penguin.fly. And now, if we actually run that. You can see, we actually get the message quite correctly, still, that in the case of the bird Australian ringneck is pecking, flitting from branch to branch, and we only printed out the fly method for penguin. I'm not very good at that, can I go for a swim instead? So, you can see that's working quite nicely. So I'm gonna end this video here. In the next video what we're gonna do is start talking about how this is different to an interface and how to decide whether to use an interface or an abstract class. So, I'll see you in the next video.