OOP - Inheritance in JavaScript

OOP Inheritance Overview

OOP Inheritance Overview

What is inheritance?

Inheritance is one of the core concepts of object-oriented programming.
It allows the programmers to reuse code. Instead of writing the same code, again and again, we can simply inherit the properties of one class/object into the other.
animal_inheritencej

Classical (class-based) Inheritance

Classes inherits from classes!

Classical (class-based) Inheritance

The inheritance is based on copies! I.e. when a child class inherits its parents members, they are actually copied to the child class.
The Cons?
Gorilla / Banana problem
Tight Coupling Problem
Duplication by Necessity Problem

Prototypal Inheritance

Objects inherits from objects!

Prototypal Inheritance

The inheritance is based on a prototype chain! As a result, each child will be able to access by reference its prototype (parent) object.
Pros?
Prototypes are flexible. They may be either mutable or immutable.
Dynamic changes in prototype will reflect the child objects!
It's simple. You only have objects and extending objects is the only operation required

How Prototypal Inheritance works?

Let's got deep - what's in a object?

at Object Literal


			var car = {};
		

at Constructor (what does it do?)


			var Car = function(){};
			var ford = new Car();
			var BMV = new Car();
		

at Factory


			var carFactory = function(){ return {} }
			var ford = carFactory();
			var BMV = carFactory();
		

Factory vs Constructor


			function CarConstructor(){};

			CarConstructor.prototype.sayHello=function(){
				console.log(`Hello from CarConstructor.prototype`);
			}
			// creating objects with Constructor will set the "__proto__" to the Constructor.prototype
			var constructedCar = new CarConstructor();

			constructedCar.sayHello();
			//Hello from CarConstructor.prototype

			function CarFactory(){
				return {}
			};
			CarFactory.prototype.sayHello=function(){
				console.log(`Hello from CarFactory.prototype`);
			}
			// creating objects with factory will NOT set the "__proto__" to the Factory.prototype
			var fabricatedCar = CarFactory();

			fabricatedCar.sayHello();
			//TypeError: fabricatedCar.sayHello is not a function
		

Classical (class-based) Inheritance in JavaScript

example


			// create 'Car' constructor
			var Car = function(manufacturer, speed){
				this.manufacturer = manufacturer || undefined;
				this.speed= speed || 100;
			}
			Car.prototype= {
				drive: function(){
					if (this.wings >= 2){
						console.log(`Flying wiht ${this.speed} km/h`);
					}else{
						console.log(`Driving wiht ${this.speed} km/h`);
					}
				}
			}

			// create 'Ford' constructor
			var Ford = function( speed){
				var manufacturer = 'Ford';
				// use the parent constructor
				Car.apply(this, [manufacturer, speed]);
			}
			// set the prototype chain
			Ford.prototype.__proto__ = Car.prototype;

			// create 'ford' object
			var ford = new Ford(200);

			// create 'theFordOfPesho' object
			var theFordOfPesho = new Ford(300);
			theFordOfPesho.wings = 2;


			ford.drive();
			theFordOfPesho.drive();
		

diagram

Prototypal Inheritance in JavaScript

The Prototype Chain

Each JavaScript object has a prototype object
An object "inherits" - i.e. has access to all members of its prototype.
An object prototype is just an object, so it can also have prototype from which to inherit from.
This is known as the prototype chain!

Prototypal Inheritance of Object Literals using '__proto__' - example


			// create 'car' object
			var car = {
				manufacturer: undefined,
				speed: 100,
				drive: function(){
					if (this.wings >= 2){
						console.log(`Flying wiht ${this.speed} km/h`);
					}else{
						console.log(`Driving wiht ${this.speed} km/h`);
					}
				}
			}

			// create the 'ford' object
			var ford = {
				// make 'ford' to inherit from 'car'
				__proto__ : car,
				manufacturer: "Ford",
				speed: 200,
			}

			// create 'theFordOfPesho' object
			var theFordOfPesho = {
				// make 'theFordOfPesho' to inherit from 'ford'
				__proto__ : ford,
				wings: 2,
				speed: 300,
			}

			ford.drive();
			theFordOfPesho.drive();
		

Prototypal Inheritance of Object Literals using '__proto__' - notes

Be careful when using __proto__
Prototype_mutation on MDN
Do not use __proto__ outside of object literals!

Prototypal Inheritance of Object Literals using '__proto__' - diagram

Prototypal Inheritance of Object Literals using Object.create() - example


			// create 'car' object
			var car = {
				manufacturer: undefined,
				speed: 100,
				drive: function(){
					if (this.wings >= 2){
						console.log(`Flying wiht ${this.speed} km/h`);
					}else{
						console.log(`Driving wiht ${this.speed} km/h`);
					}
				}
			}
			// create 'ford' and make it to inherit from 'car'
			var ford = Object.create( car, {
				manufacturer: {value: "Ford"},
				speed: {value: 200},
			})

			// create 'theFordOfPesho' and make it to inherit from 'ford'
			var theFordOfPesho = Object.create(ford, {
				wings: {value: 2},
				speed: {value: 300},
			})

			ford.drive();
			theFordOfPesho.drive();
		

Prototypal Inheritance of Object Literals using Object.create() - diagram

Yes, the diagram is identical with the one with '__proto__'
It's better and safe to use Object.create() aproach, instead of '__proto__'

Prototypal Inheritance of constructed objects


			// Animal constructor
			var Animal = function(food){
				this.food = food;
			}
			Animal.prototype.eat = function(){
				console.log(`${this.name} is eating ${this.food}`);
			}

			// Cat constructor
			var Cat = function(name, food){
				// reuse the Animal Constructor
				Animal.call(this, food);
				this.name = name || 'Tom';
			}
			// Cat objects will inherit from Animal.prototype
			Cat.prototype = Object.create(Animal.prototype);

			// Cat instance
			var tom = new Cat('Tom', 'cheese');
			tom.eat();
		

Reference

Reference

More on __proto__, [[prototype]] and prototype

Exercises

Exercises

Developer_Manager_Person - Task Description

Create a Person Constructor with following fields:
name: string
age: numbers
greet: function, which prints out 'Hi, I'm ${this.name} and I'm ${this.age} years old'
Create a Developer Constructor with following fields:
name: string
age: numbers
skillset: array of a developer skillsets
Create a Manager Constructor with following fields:
name: string
age: numbers
managed: array of developers being managed
The Developer and Manager objects should reuse the Person Constructor and should inherit from Person the greet method!

Developer_Manager_Person - Template

You can use the next code template to bootstrap your solution:


			/* --------------------------- Person constructor --------------------------- */
			function Person(name, age){
				// your code here ...
			}
			// Person greet method
			// your code here ...


			/* --------------------------- Manager constructor -------------------------- */
			function Manager(name, age, managed){
				// reuse Person constructor
				// your code here ...
			}
			// Manager objects should inherit all methods from Person:


			/* -------------------------- Developer constructor ------------------------- */
			function Developer(name, age, skillset){
				// reuse Person constructor
				// your code here ...
			}
			// Developer objects should inherit all methods from Person:

			/* ----------------------------- Create Objects ----------------------------- */
			// Developer instances
			let maria = new Developer('Maria Popova', 23, ['Python', 'Machine Learning']);
			let pesho = new Developer('Petar Petrov', 19, ['JavaScript', 'Angular', 'React', 'Vue']);

			// Manager instances
			let gates = new Manager('Bill Gates', 43, [maria, pesho]);

			/* ----------------------------- Use the objects ---------------------------- */
			maria.greet();
			pesho.greet();
			gates.greet();
		

Developer_Manager_Person - Expected Results


			Hi, I'm Maria Popova and I'm 23 years old

			Hi, I'm Petar Petrov and I'm 19 years old

			Hi, I'm Bill Gates and I'm 43 years old
		

Developer_Manager_Person_Advanced - Task Description

Overwrite the greet() method for Developer and Manager objects, such that the same code execution as given in the previous task template will produce next output:

			Hi, I'm Maria Popova and I'm 23 years old
			I know Python,Machine Learning

			Hi, I'm Petar Petrov and I'm 19 years old
			I know JavaScript,Angular,React,Vue

			Hi, I'm Bill Gates and I'm 43 years old
			I manage Maria Popova,Petar Petrov,
		

These slides are based on

customised version of

Hakimel's reveal.js

framework