Today we take flight! The first session introduces static class functions. These will help us add a new layer of interactivity to our airports exercise. We then look at inheritance, a core concept of object oriented programming (OOP).
You need to have completed the work on airports so you have a codebase with the following classes defined and tested:
Previously we have been created objects using classes and the new keyword. We have been constructing data structures in our code. For example the plane class contained passengers and each passenger had 1 or more bags. To complete our programme we really want to be able to move our planes (and the passengers they contain) from one airport to another.
To do this, we need to be able to access one airport from another airport. We can't do this using the properties and functions of an instance of an airport. For example if we created London Heathrow (LHR). Then Los Angles (LAX). How can we connect them?
london.addAirport(LAX)
You can see that is clumsy, hard to keep track of. Each new airport needs to be in sync with all the rest.
You can tell we need somewhere we can keep all the airports that we create. If we use a static class property we can easily keep all the instances of the airports we create in one place. Read the code snippet below. Can you see what we are doing here?
class Airport {
static airports = []
constructor(name) {
this.name = name
this.planes = []
this.constructor.airports.push(this)
}
land(plane) {
this.planes.push(plane)
}
}
On the Airport class itself we are able to access each instance of an airport that is created Airport.airports is an array of all instance of Airport.
Can you write the takeOff function on an instance of an airport that should take a plane as an argument, find that plane in the airport's planes array and remove it, then push it into the inbound airport's array of planes. This will effectively move the plane object from one airport to another.
Remember to write tests that prove all the functionality that we have talked about.
The final object orientated pattern we are going to look at is inheritance. This is a way to share functionality in an object orientated paradigm. The idea is very simple. You extend base classes that already exist with additional functionality. If we look at our airports system we have 2 kinds of travellers.
| Passengers | Crew |
|---|---|
|
|
Both are people, both have a name and bags when they travel.
PersonA base class is the base from which you might create other types of classes. Lets refactor our code to use a base class Person. A person will have a name and bags - basically the current Passenger class definition we have now needs to be renames to be Person. Now to restore our Passenger class we should import the base class into our Passenger definition and extend it like this.
const Person = require('./Person')
class Passenger extends Person {}
That is enough to fix all our current tests. Everything should work as it was. When we create a new Passenger('bob') we will be able to call addBag as this functionality has been inherited from the Person class. Our passengers might want particular functionality like callAttendant.
const Person = require('./Person')
class Passenger extends Person {
callAttendant() {
console.log('Excuses me, Hay there!')
}
}
Can you see where this is going? One useful operator I want to introduce at this point is instanceof. Now you can make classes, in your code some times you'll want to know what an object is. For example, you might want to know is this person a Passenger or a Crew member? You can use instanceof to help you work that out.
test('is an instance of a Passenger', () => {
const betty = new Passenger('Betty')
expect(betty instanceof Passenger).toBeTruthy()
})
Crew class by extending the Person class? Think about the properties a crew member may have.Plane class to have a crew propertyboard is called on an instance of a plane, you should iterate over the array and put crew and passengers in the correct property in the plane instance.When you have completed these tasks can you create a coverage report using Jest. Add the following line to your package.json
{
"scripts": {
"test": "jest --watchAll",
"test:report": "jest --coverage=true"
},
"dependencies": {
"jest": "^26.4.2"
}
}
Then run npm run test:report you are aiming for 100% test coverage. When you run this you should see that Jest generated a 'coverage' report in your project folder. If you navigate to /coverage/Icov-report/index.html and open it in your browser you'll see a helpful report of your test coverage.
This is interactive try clicking on one of the class definitions.