# 0.4.4: Classes

## Learning Objectives

1. Understand the motivation behind JavaScript classes and object-oriented programming (OOP)
2. Understand how to use JavaScript class syntax to create and use classes
3. Understand how class inheritance works, how to use `super` to call parent class constructor

## Introduction

The following is an example of a JavaScript class that represents cars. For simplicity, these cars only travel 1 unit of distance per trip.

```javascript
class Car {
  // Define class properties in a constructor method
  constructor(colour) {
    this.colour = color;
    this.odometer = 0;
  }

  // Define class methods within the class block
  drive() {
    this.odometer += 1;
  }
}

// Create new "instances" of classes with the "new" keyword
const whiteCar = new Car("white");
const blackCar = new Car("black");

// Call class methods on instances of the class
whiteCar.drive();
blackCar.drive();
blackCar.drive();

// Retrieve class properties as we would with JS Objects
console.log(whiteCar.odometer); // 1
console.log(blackCar.odometer); // 2
```

JavaScript classes are templates for entities we may wish to manipulate as a unit in our apps. Classes are part of a broader computer science concept called object-oriented programming, also known as OOP. Classes are optional in JavaScript but mandatory in languages such as Java.

## Without classes

Without classes, we might store data in JavaScript Objects and manipulate them with helper functions.

```javascript
const whiteCar = {
  colour: "white",
  odometer: 0,
};

const blackCar = {
  colour: "black",
  odometer: 0,
};

const drive = (car) => {
  car.odometer += 1;
};
```

To reduce redundancy in object creation, we could write a helper function like `createCar` to generate our objects.

```javascript
const createCar = (colour) => {
  return {
    colour: colour,
    odometer: 0,
  };
};

const drive = (car) => {
  car.odometer += 1;
};

const whiteCar = createCar("white");
const blackCar = createCar("black");
```

## With classes

JavaScript classes encapsulate the entity properties (`colour` and `odometer` above), entity creation method (`createCar` above) and any entity helper methods (`drive` above) within a single unit, i.e. class. This helps us organise our code by thinking of a `Car` as a single entity, instead of an entity spread across disparate objects and helper functions.

```javascript
class Car {
  // Define class properties in a constructor method
  constructor(colour) {
    this.colour = color;
    this.odometer = 0;
  }

  // Define class methods within the class block
  drive() {
    this.odometer += 1;
  }
}

// Create new "instances" of classes with the "new" keyword
const whiteCar = new Car("white");
const blackCar = new Car("black");
```

We can represent many common app entities as classes, for example users.

```javascript
class User {
  constructor(name, email, password) {
    this.name = name;
    this.email = email;
    // Always only store hashed passwords to mitigate problems if data stolen
    this.passwordHash = hash(password);
  }

  changePassword(newPassword) {
    this.passwordHash = hash(newPassword);
  }
}

const joe = new User("Joe", "joe@joe.com", "joerox");
const amy = new User("Amy", "amy@amy.com", "amyrox");
```

Naming convention: Classes are typically named with UpperCamelCase. Instances are typically named with lowerCamelCase.

## Class inheritance

One of the most valuable features of OOP and classes is "inheritance". Inheritance allows classes to "inherit" properties and methods from one another by forming "parent-child" relationships. For example, if I wanted to create classes for `Bicycle` and `Car` vehicle types, both of which have a `speed` property and the same `calcTravelTime` method that depends on `speed`, I can define how we store the `speed` property and define the `calcTravelTime` method in a parent class `Vehicle` and have `Bicycle` and `Car` classes inherit from `Vehicle` to avoid repeating code.

{% code title="class-example.js" %}

```javascript
class Vehicle {
  constructor(speed) {
    this.speed = speed;
  }
  
  calcTravelTime(distance) {
    return distance / this.speed;
  }
}

/*
 * Bicycle and Car classes "inherit" properties and methods from Vehicle class
 */

class Bicycle extends Vehicle {
  constructor(speed) {
    // The super keyword runs the constructor of the parent class
    super(speed);
  }
}

class Car extends Vehicle {
  constructor(speed) {
    super(speed);
  }
}

// Declare new Bicycle and Car instances
const bicycle = new Bicycle(10);
const car = new Car (100);

// Even though we did not define calcTravelTime in Bicycle and Car, they have the method
console.log(bicycle.calcTravelTime(100)); // 
console.log(car.calcTravelTime(100));
```

{% endcode %}

1. Notice we use the keyword `extends` to specify inheritance in JavaScript
2. Notice we use the keyword `super` in constructor methods of child classes `Bicycle` and `Car` to call the constructor method of their parent, `Vehicle`.

Try creating a local file `class-example.js` with the above code and running it with `node class-example.js`, playing around with its features to understand how classes work!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bc.rocketacademy.co/0-foundations/0.4-javascript/0.4.4-classes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
