Instructor: Now that we are ready to use
ES6 classes, let's take it one step further
and implement inheritance between classes
using subclasses.
So, do you remember this slide
from when we first talked about inheritance?
We had this example where we had
two function constructors,
or ES6 classes,
which is like the same thing
that can inherit from one another.
So we have here the more generic class person,
for all persons,
and then we have the more specific subclass
for an athlete,
because an athlete is also a person,
but with some more specific attributes,
and also methods.
And so, it makes a lot of sense
that we make the athlete class
inherit from the person class, right?
Now, we have actually never implemented
this in our code up until this point.
All we did was to make objects
inherit methods from their prototype.
But this inheritance between classes
is really taking it even one step further,
and so that's something really cool,
and sometimes really useful, too.
So, such as before,
let me first show you how to do it in ES5,
and then we move on to classes and subclasses with ES6.
First of all, let's get back
the code that we wrote before for ES5,
so that we don't have to write it all over again.
So, this Person5 function constructor,
or let's call it class,
will be our superclass.
So, let's now create the subclass,
which will be the athlete class,
and this is how we do it.
So, Athlete, and five again,
is a function,
and in this function, we actually
have to pass in these exact same parameters here,
as well.
So, let's just copy them.
Okay, so if you want an athlete,
we need to say their name, their year of birth,
their job, and we also want to define
to how many Olympic games they went.
So, let's call it olympicGames,
and also, how many medals they have won.
So, medals.
Okay, and now, in this subclass
the first thing that we have to do
is to call our superclass, which is Person5, right?
So, let's do that.
Person5, and we actually now have to use
the call method,
and I'm gonna explain you why
in a second, okay?
Let's first write the code,
and then I'm gonna explain it to you.
So, this will be set to this,
and then we pass in the three arguments that we have.
So name, yearOfBirth, and job.
And we can only pass the three arguments into here
because we received them
in this function call, here, as well, right?
And that's why we have to have them here,
and also in here.
Okay?
And now, it works like just it worked before,
so we say olympicGames
is equal to olympicGames, of course,
and this.medals is medals.
So, why do we have to call
the superclass function constructor
with this as a this keyword?
And I'll give you a second to pause the video
and think about that.
To explain this, we need to remember
how the new operator works,
which is the operator that we use
to create a new instance.
So, when creating a new athlete object,
new creates a new empty object,
calls the athlete function constructor,
and sets the this keyword
to the newly created empty objects.
So, you remember that part, right?
So, in execution context that we're in here,
the this keyword will point to the new empty object.
Now, if we want a person property's name,
year, and job to be set
on the new athlete object,
then we need to call the person function constructor
with the this keyword also set
to our newly created athlete object, right?
And that's exactly what we do here.
So, after this, all the properties
will be set in the new athlete object
that's created by the new operator,
and that's why we need to call it here,
and to set the this variable to this.
Alright, and now to create
the correct prototype chain,
we're gonna use object.create,
because, remember, object.create
allows us to manually set the prototype of an object,
and we want the prototype of the athlete
to be the prototype of the person,
so that they become connected.
So, let's quickly do that
and say Athlete5.prototype
Object.create
(Person5.prototype),
and that's it.
So now, the two function constructors
are connected, and the prototype chain
should work just fine.
So, let's actually take a look
at that in the console,
and so I'm gonna create a new athlete tier,
and I'll say johnAthlete5.
So, it's a new athlete
called John,
so, remember, we have to set all of these properties
that we would set on the person,
also on the athlete.
So, John, born in 1990,
now let's say that he's a swimmer,
that he went to three Olympic games,
where he won 10 medals.
So, quite a great athlete.
And let's now reload this,
and take a look at John the athlete.
Okay, so here we go.
So we see all of our properties
are defined here in the athlete,
and we also see that our prototype is the Person5,
and that means that the Athlete5 function constructor's
prototype property
is the same that Person5's prototype property.
And so, in here, we have the prototype of Person5,
and then, of course, we have
the calculate age function, here.
And what this means is that the prototype chain
works exactly in the way that I showed you
in a section where we talked about all of this.
So, let's now test this.
I'm gonna write johnAthlete5.calculateAge,
and if I now reload this,
then we actually get this error here.
Alright.
So, something must be wrong here
in this method, okay?
So, let's take a look, new date,
okay, and here it is.
So this, of course, is a method,
so getfulYear is a method,
and that's why it wasn't working, probably.
So, let's try it again.
Alright, so 26 is the age,
and that, once again, works because
not only all the instances
of person can now inherit this method,
but also, all the instances
of the athlete class can inherit this method,
because, as we did here in this line,
the Athlete5 class inherits
from the Person5 class.
So, again, Person5 is the superclass,
and Athlete5 is the subclass.
And, of course, we can also set
methods on the prototype property
of the Athlete5 function constructor.
Let's do that.
.prototype.wonMedal
This is a method that's very specific
only to the athletes,
and so all the instances
are going to inherit this method
if they are athlete instances, of course.
And the Person instances,
they will not inherit this method,
because it's only in the Athlete5
prototype property.
So, this method will, very simply
increase the medals of the athlete.
Plus plus, so increase by one,
and then log it to the console.
And so, now, we can also use this one here.
Won a medal.
Let's try it out,
and we got an error
saying that one medal is not a function,
and that's because it actually has to be
after we connect these two function constructors
with this line of code, here.
So, we first set the Athlete5 prototype property,
and then we can add methods
to that very prototype property.
Okay, and so now it's gonna work,
and we see that he has 11 medals now.
So, we started with 10, and now we have 11.
Let's now just take
a final look at the object in the console.
Now, we'll also find the wonMedal here,
in its prototype property,
which is exactly what we did here.
And then, of course,
also the calculate age function, here,
further down in the prototype chain.
Great, so now you learned
how to connect to function constructors in ES5,
so let's now do the same thing in ES6.
Once again, first I'm going to get back this class.
Okay.
So, this is for ES6,
and this here is our person.
Let's just get rid of this method
that we don't want,
and let's focus on what we need.
So, we have our superclass here,
and now comes the fun part,
where we create a subclass of the person,
and this is actually way easier to do in ES6
with ES6 classes
than with the function constructors
like I showed you before.
All we have to do
is to say, once again, class,
and this one is called Athlete6,
and then we just use the extends keyword.
So, we say that this class extends the person class.
Okay, and so, always,
in the subclass, we need to say
that it extends the superclass.
And then we, of course,
once again need a constructor,
and, remember, all classes
need to have this very method.
And then, in the same fashion
as we had to do before with function constructors,
we have to repeat the person properties here
if we also want them on our athlete.
So, name,
yearOfBirth, job,
and now, remember, what we want to add here is
olympicGames,
and medals.
Now, what we did before,
was to then use, in the subclass,
this call method to call the superclass,
with the this variable set to this.
Now, here in classes, we have to do something similar,
but it's also easier, because all we have to do
is say super,
and this will then call the superclass.
And we don't have to manually
set any this variable or anything.
Everything happens automatically
behind the scenes,
and we don't have to take care
of any of that.
So, of course, we call the superclass
using name, yearOfBirth,
and job.
And that makes sense, right?
Because these are the exact same parameters
that we have in the constructor
of that class.
And now we just say
this.olympicGames
is equal to olympicGames,
and the medals are medals.
And that's it.
Let's also add our method, here.
And so, it's the same code as we had before,
so this.medals
will be incremented by one unit,
and then let's just
log it to the console.
So, let's use this class
and create yet another johnAthlete.
So, John, born in 1990,
he's a swimmer,
went to three Olympic games,
where we won 10 medals.
And just to check that everything works the same,
we're gonna call the same methods that we called before,
so johnAthlete6.wonMedal
and johnAthlete6.calculateAge
So, let's check it out,
and we have a bug.
Super keyword is not expected here,
so here, it's not expected.
It's actually because this is misspelled,
so constructor.
Okay, so now it should work.
And yeah, here we go.
It now says that the age is not a number,
but that happened because
we also had this bug here that we had before,
so if we fix this,
then it's gonna work here, as well.
So, it gives us the same age
and the same medals, so everything works the same.
But, if you take a close look at it
then you have to agree that it's way easier
to write it this way here,
these two class definitions,
than to write all of this here up.
Just, everything like this,
and to have to add up this line of code, here,
and it all looks a bit strange.
I clearly prefer to do it the ES6 way,
with the class definitions.
All we need to make sure
is that we really understand
what happens behind the scenes,
and what prototype inheritance is
and how it works,
and why doing these classes like this
works the way that it does.
And, just to show you once again
that these classes are just synthetic sugar,
let me show you these
athletes here, as well, in the console,
so to prove to you again
that they look the exact same way.
So, this is the functioning prototype chain,
in the way we did it before
with Athlete5 and Person5,
and then, what we did right now,
and so we see, if you make this bigger,
that it's the exact same thing.
So this prototype chain, here,
is the exact same as this prototype chain.
Alright, and so with these two final lectures
about classes,
you now truly understand everything
that there is to know
about prototype inheritance and classes
in both ES5, and also ES6,
which is really great.