(upbeat music)
In this video we're gonna look at
extending the Vampyre class to create a super Vampyre.
Now, it's going to be very similar
to what we've already done,
but there's a couple of other things
we need to know how to do.
So we're gonna create a vampyre king subclass
of Vampyre.
Now, our vampyre king is going to be incredibly powerful,
and any points of damage inflicted will be
divided by four.
Vampyre king objects will also start off
with 140 hit points and as you see,
that's where we need to look a bit deeper
into Kotlin inheritance.
So we're gonna start by extending Vampyre
to create a vampyre king class
with those additional properties.
First thing we need to do is start by making
the Vampyre class open.
So let's do that.
So that it can now be inherited from.
And now we need to create our new vampyre king class.
I'm going to do that.
Right click Java folder, New, Kotlin Class
save a bit of typing by selecting Class
and the name of your VampyreKing.
Now we need to pass the name to the class
and provide that to the Vampyre class.
So, the end of the definition
open parentheses, name colon String,
then outside the right parentheses,
colon Vampyre,
then parentheses, name.
That's straightforward, but where it gets tricky
is setting the VampyreKing's hit points to 140.
Now if we look at the Vampyre class,
it passes the fixed value 20 to the enemy constructor.
Now we need to change that to 140 somehow.
Now, one way we could do that is to use a default value,
and we can modify the Vampyre class
to have a hit points parameter,
with a default value of 20,
that we can then pass to the enemy constructor.
So let's try that first.
So we'll add the parameter, hitPoints colon Int
and set the default value of 20.
Then we need to change
the hardcoded value here to hitPoints.
So now that we've done that,
we can go back to the Vampyre constructor
in the VampyreKing class,
and we can change that to 140.
So let's see if that works
before we talk some more about it.
So we go back to our main function,
and let's add or create a VampyreKing instance.
So val dracula is equal to
VampyreKing parentheses Dracula.
And let's print the value of that as well,
so println(dracula).
So let's run that and see if it works.
Okay so that's good, we can see that it does work.
Dracula, as you can see down at the bottom here,
has got 140 hit points.
So that's one way to do it,
and it's a perfectly-acceptable solution,
but you can probably tell that I'm itching to show you
another way.
So, what's wrong with what we've just done?
Well, it's compromised our Vampyre class slightly,
because we can now create Vampyre instances
with less than 20 hit points.
So if you go and modify the code on line eight,
that creates Vlad,
we can use that second argument now, and say,
set the hit points to two.
Now, before I run the programme again,
notice in the output
that Vlad started off with 20 hit points,
and that dropped to 16 after we inflicted the damage.
But if we run it again now,
what's happened this time is
because he only started out with two hit points,
poor old Vlad's lost a life
with the damage that's been inflicted on him.
Now the change we made to the Vampyre class
now allows vampyres to be created with a different number
of hit points.
And that may be fine, depending on your application.
Sometimes, though, you'll want to provide a default
but allow the users of your class to change it.
Sometimes, though, it'll be very important
that some properties can't be altered in this way.
Now, as an example, consider an arc class,
that draws an arc, through a specified number of degrees.
Now, we may override this to create a circle class,
which will have the number of degrees fixed at 360.
Now we certainly don't want to draw circles
that don't have 360 degrees, because of course,
they wouldn't be circles.
So, getting back to our code though,
we can define our enemy objects to be whatever we want.
There are inventions if you'd like,
but when we're modelling real physical objects,
we want our classes to really respect
those physical constraints.
And that's why sometimes this approach won't be appropriate.
And another important reason is that
we might be extending someone else's class,
and if we don't have the source code available,
then we can't make changes to it,
and that would rule out this approach.
So what I'm gonna do is undo these changes,
and Command + Z is a very useful shortcut.
That undoes the last change we made.
On a PC that's Control+Z.
So rather than editing my changes,
I'm gonna use Control + Z to undo them.
So, firstly in main, we're going to undo the changes to Vlad
to get rid of the extra line there
that was passing the number of hit points.
Then back in the Vampyre class,
let's undo those changes as well.
We'll remove hitPoints, and the default value as well,
and that will mean that when we go back
to the VampyreKing class, of course we've now got an error,
because we're using the 140.
So I'm going to undo that as well,
so that we have it back to how we had it before.
So how can we now set the hit points
for our VampyreKing to 140?
Well, what we can do instead, is to use it in an init block
in VampyreKing to change the hit points value.
So we can type in init, then left and right curly braces,
and within the code block,
we can assign hitPoints equal to 140.
Now what does does is changes the value of hit points
when an object gets created.
Now init code's executed at the time
that we create the instance.
And it's done automatically,
so we don't have to remember to do anything special.
So if we run this programme,
given that we've deleted those changes,
we can see that Dracula is now still set at
getting his hit points set to 140,
but we haven't compromised the Vampyre class in any way.
Basically, we've extended the Vampyre class
and changed the hit points for our VampyreKing,
without having to modify the VampyreKing's superclass.
Alright, so all that remains now
is to override the takeDamage function
to divide the damage by four.
Now, if you recall, I've already done something similar,
with the Vampyre class, I used the takeDamage,
so let's do something similar here.
Here, VampyreKing class, and then override takeDamage,
and what I'm going to do is set that damage
into divided by two there.
Remember that we're trying to overall
change the damage by four,
divide the total damage taken by four.
And in fact, that's exactly the same code now
that we've got into the Vampyre class.
That's the, if you recall, the Vampyre class,
that's already setting the damage,
dividing that damage by two.
We're doing the same thing here in takeDamage
for the VampyreKing class,
so we're only dividing it again by two here and not by four.
So it is important to understand exactly which class
is the superclass here.
Now, VampyreKing extends Vampyre,
so the super method that we're calling
is the Vampyre method, and not the enemy method.
So what happens is that the VampyreKing takeDamage method
calls the method in its superclass, which is Vampyre.
Now the Vampyre class takeDamage method,
it calls its superclass method, or function,
so that it calls the enemy takeDamage function.
Now Android Studio has a really useful feature
to help understand all this.
So back in the VampyreKing class, which I've got open,
I can hold down the Command key, 'cause I'm on a Mac,
but it's Control on a PC,
and click on the takeDamage,
in its call to super.takeDamage,
and I click on that, and you can see that
it's automatically jumped to the Vampyre class,
or rather the takeDamage function in the Vampyre superclass.
Now if I do that again, in this class,
you can see it's now jumped to the takeDamage function
in the enemy class.
So basically that's the superclass of Vampyre.
So you can follow the trail back,
and that's great for checking
exactly what these overridden functions are doing.
Okay, so we only have to divide the damage by two
in the VampyreKing class again,
and that's because it'll be divided again
when the Vampyre takeDamage method is called,
in other words, when this code is executed,
which is also going to be divided by two.
So, let's see if it works,
by inflicting some damage on Dracula in the main function.
So we'll do dracula.takeDamage(12).
And we'll run that.
So when we run the programme, we can see that Dracula
starts off with 140 hit points,
but then inflicted 12 points of damage,
but that gets divided by two
in the VampyreKing's takeDamage method,
then divided by two again in the Vampyre class.
So we only inflict a total of three hit points
of damage on Dracula.
So Dracula ends up with 137 hit points left,
three points of damage, which is correct.
Alright, so I'm gonna stop the video here,
and in the next one, we're gonna look at using loops
to repeat a section of code.
We're actually gonna use a loop
to repeatedly inflict damage on Dracula,
so that hopefully, we can slay that brute.
See you in the next video.