-: Hi guys, and welcome back!
In this video, we're going to start talking
about class inheritance.
Inheritance allows one class to take some methods
and properties from another class.
Let's have a look.
Imagine you've got a class called Device,
such as a USB device or something like that.
And you want it to represent just anything
you might plug into your computer.
So I'm going to define my init method,
and then we're going to be able to give these devices names
and how they are connected, such as by a USB.
So I'll say, connected by.
Then we'll say self.name=name,
self.connected by=connected by,
and we're also going to assume
that when you create a device object,
that is going to represent a connected device,
something that is already connected to your computer.
So we'll say self.connecte=true.
We are going to assume that it's connected
and we don't have to pass in a parameter for that.
We can just say true here.
Then, we will type str and we're gonna say return f
device self.name, and we're going to put !r
and we're gonna say self.connected_by.
The exclamation mark r,
calls the repr method of self.name,
so that it shows up as having the quotes already.
So this is just a little bit nicer
than putting the quotes in yourself.
Then we're also going to add a disconnect method,
which just says self.connected=false
and the prints out disconnected.
So you have this class device here.
This device doesn't do much at the moment,
but you could do something like printer=device
and call it Printer and say it's connected via USB,
and then you can print it out.
Finally, you can also disconnect it.
All right, let's press play.
And you can see that you get Device, Printer, USB,
and then disconnected, so very good.
Now, let's say you want to add functionality to this class
that allows it to print things out.
For example, it can print a certain number of pages,
or something like that.
This class here is not a printer, this is a device.
Could be a printer, but it could also be a webcam,
or a microphone, it could be anything.
So we don't want to add
printer specific functionality to this class.
You could rename the class and turn it into a Printer class,
but you can also create another class
that uses all of these methods and has more,
and that is where inheritance comes in.
So we're going to create a printer class now,
and we're going to do something new,
which is put a pair of brackets after it,
and here we're going to put Device.
And what this tells Python
is that you're creating a new class called Printer
and it inherits from Device, which means that it will
essentially copy and paste all of these methods.
It won't quite do that,
but you will be able to use these methods from this class.
So, let's start by defining an init method.
Now, this printer object is going to need a name,
just like a device, e-connected by just like the device,
and it's also going to have a capacity.
How many pages left of ink?
Then, what we're going to do is,
instead of doing self.name=name,
self.connect by=connected by, self.connected=true.
Instead of doing that,
which as you can see is a copy paste of this method here,
we can just call the parent class device init method.
So, what to do in Python 3, is to do super.init.
So, super and then a pair of brackets,
and what this does in Python
is it gets the super class, or the parent class,
which in this case is Device,
and it's going to call the init method of that super class..
Of course, the init-method needs a name and a connected by,
so we would pass a name and connected by.
These are two parameters.
We still have capacity.
So, we will say self.capacity=capacity
and self.remaining pages=capacity.
Why am I doing two properties with the same value?
The capacity is the maximum amount of pages
that a printer could potentially print, if it had full ink.
Whereas the remaining pages is how many are left
after printing some.
So, you can think of this as maximum capacity
and this as current capacity.
Then, we are going to define an str method,
and here we're going to return
the super classes str method.
And then we're also going to put in self.remaining pages,
pages remaining, something like that.
Of course, do remember to put in your quotation marks.
You will need them and your f-string.
So now, we're going to print out this entire thing,
Device printer, USB,
and then we're gonna say remaining pages 100, or something.
And finally, we're going to put
in our printer specific method, which is the print method.
Here, we're going to be able
to print a certain number of pages.
So we will say that if not self.connected,
then we will print your printer is not connected.
Otherwise, we're going to say print printing pages that,
and then self.remaining pages-=pages.
Of course, we do have to return here,
so that we exit the function if we're not connected.
Otherwise, we will print this and then that,
which is not what we want.
So, now we have our two classes;
the printer and the device class.
You can still use it, Device class on its own if you want.
It's in no way related to the Printer class,
so the Device class knows nothing about Printer.
But the Printer class is related to the Device.
It knows about it, it is the child of it.
So, you can now create a printer and say
Printer, printer, USB, and say 500 pages of capacity.
And then, you can do printer.print and print 20 pages out,
and then you can print your printer.
This is all a bit confusing
because I've gone for the name printer,
which may not be the best one, but oh, well.
So, we forgot an f-string here.
Make sure to add that in.
Then, we're gonna run it again.
So, you get Printing 20 pages,
and then your Device, printer, USB, 480 pages remaining.
Here, we've used inheritance to build out our methods,
like our init methods and our str method
by using the parent-class-methods, such as here and here.
In addition, this printer
can still use the disconnect method
that was defined in the Device class.
And what happens when you do printer.disconnect
is that Python will try to look for the disconnect method
inside the Printer class.
But upon not finding it,
it will try to look in the next parent class,
which is Device, and it will find it there.
The Device class actually inherits from another class,
as well, which is the Default inheritance,
and that is Python's object class.
So, if you call a method that is not in the Printer
or the Device class, Python will then go to the Object class
and see if it's there.
And if it's not there, then you'll get an error.
So those are the three levels of calling
that you will see when you use the Printer class.
First, the printer will be checked.
Then, the Device will be checked.
Finally, the object will be checked,
and if none of them has the method
or the property you're trying to access,
then you'll get an error.
Let me just run that,
and you can see that you get disconnected there.
Of course, if you do printer.print, and you try to print
30 after you've disconnected,
then you will see your printer is not connected.
Hopefully, all of this makes sense.
Inheritance in Python is much simpler
than in other programming languages.
All that happens is there is a hierarchy for calling things.
When you try to call a method,
or access a property of a class,
that just goes up the hierarchy, and that's it.
You can always use the Super class within a class.
So, you can access that class' methods,
such as what we're doing here and here.
Thanks for joining me in this video.
I hope you've enjoyed it,
and I'll see you in the next one.