Some classes can inherit from others. Inheritance allows you to reduce the amount of code in the derived classes. For example, take the following classes:
class Person { name; age; print() { console.log(`Name: ${this.name} Age: ${this.age}`); } } class Employee { name; age; company; print() { console.log(`Name: ${this.name} Age: ${this.age}`); } work() { console.log(`${this.name} works in ${this.company}`); } } const alex = new Person(); alex.name = "Alexander"; alex.age = 33; const bob = new Employee(); bob.name = "Bob"; bob.age = 36; bob.company = "Google"; alex.print(); // Name: Alexander Age: 33 bob.print(); // Name: Bob Age: 36 bob.work(); // Bob works in Google [js] Two classes are defined here - <em>Person</em> which represents a person and <em>Employee</em> which represents an employee enterprises. Both classes work great, we can create objects of them, but we also see that the <em>Employee</em> class repeats the functionality of the <em>Person</em> class, since the employee is also a person, for whom you can also define the name and age properties and the <em>print</em> method. Inheritance allows one class to automatically get the functionality of other classes and thus reduce the amount of code. To inherit one class from another, use the <em>extends</em> keyword. The keyword <i>extends</i> is placed after the name of the derived class, after which comes the name of the class we want from inherit functionality. [js] class Person { name; age; print() { console.log(`Name: ${this.name} Age: ${this.age}`); } } class Employee extends Person { company; work() { console.log(`${this.name} works in ${this.company}`); } } const alex = new Person(); alex.name = "Alexander"; alex.age = 33; const bob = new Employee(); bob.name = "Bob"; bob.age = 36; bob.company = "Google";
Class inheritance with a constructor
Along with all the functionality, the derived class also inherits the constructor of the base class. For example, we define in the base Person class constructor:
class Person { constructor(name, age) { this.name = name; this.age = age; } print() { console.log(`Name: ${this.name} Age: ${this.age}`); } } class Employee extends Person { company; work() { console.log(`${this.name} works in ${this.company}`); } } const alex = new Person("Alexandr", 33); tom.print(); // Name: Alexander Age: 33 const bob = new Employee("Bob", 22); //inherited constructor bob.print(); // Name: Bob Age: 22
Defining a constructor in a derived class and the super keyword.
A derived class can also define its own constructor. If a derived class defines a constructor, then the base class constructor must be called. To refer a derived class to the functionality of a base class, in including to refer to the base class constructor, the super keyword is used:
class Person { constructor(name, age) { this.name = name; this.age = age; } print() { console.log(`Name: ${this.name} Age: ${this.age}`); } } class Employee extends Person { constructor(name, age, company) { super(name, age);//inherit the parent constructor this.company = company;//let's add the constructor } work() { console.log(`${this.name} works in ${this.company}`); } } const alex = new Person("Alexandr", 33); alex.print(); // Name: Alexandr Age: 33 const sam = new Employee("Sam", 25, "Google"); sam.print(); // Name: Sam Age: 25 sam.work(); // Sam works in Google
Overriding base Class methods
A derived class, as in the case of a constructor, can override the methods of the base class. Let’s look at an example:
class Person { constructor(name, age) { this.name = name; this.age = age; } print() { console.log(`Name: ${this.name} Age: ${this.age}`); } } class Employee extends Person { constructor(name, age, company) { super(name, age); this.company = company; } print() { console.log(`Name: ${this.name} Age: ${this.age}`); console.log(`Company: ${this.company}`); } work() { console.log(`${this.name} works in ${this.company}`); } } const sam = new Employee("Sam", 25, "Google"); sam.print(); // Name: Sam Age: 25 // Company: Google
Method Part Inheritance
However, in the code above, we see that the first line of the print() method in the Employee class is essentially the same code as the print() method from class Person.
In this case, it’s just one line, but in another situation, the repeated code could be longer. And not to repeat, we can just refer to the implementation of the parent class Person’s print() method via super:
class Person { constructor(name, age) { this.name = name; this.age = age; } print() { console.log(`Name: ${this.name} Age: ${this.age}`); } } class Employee extends Person { constructor(name, age, company) { super(name, age); this.company = company; } print() { super.print();//we inherit the method from the parent class console.log(`Company: ${this.company}`); } work() { console.log(`${this.name} works in ${this.company}`); } } const alex = new Employee("Alexandr", 33, "Google"); alex.print(); // Name: Alexandr Age: 33 // Company: Google
Inheritance and private fields and methods
When inheriting, keep in mind that a derived class can access any functionality of the base class, except private fields and methods. For example:
class Person { #name; constructor(name, age) { this.#name = name; this.age = age; } print() { console.log(`Name: ${this.#name} Age: ${this.age}`); } } class Employee extends Person { constructor(name, age, company) { super(name, age); this.company = company; } print() { super.print(); console.log(`Company: ${this.company}`); } work() { console.log(`${this.#name} works in ${this.company}`); // ! Error - field #name not available from Employee } }