DevLeague Coding Bootcamp
DevLeague is a Full Stack Coding Bootcamp
And
JavaScript doesn't natively support multiple inheritance, but we can use a design pattern called a mixin.
A mixin is a design pattern where you iterate over multiple objects properties to combine them into a single new object.
function extend(destination, source) {
for (var k in source) {
if (source.hasOwnProperty(k)) {
destination[k] = source[k];
}
}
return destination;
}
And now you have multiple inheritance.
This method allows us to inherit from (extend) as many other object's as we want.
function extend(destination, source) {
for (var k in source) {
if (source.hasOwnProperty(k)) {
destination[k] = source[k];
}
}
return destination;
}
function Taco(){
}
Taco.prototype.eat = function(){
/*do stuff*/
};
function Beans(){
}
Beans.prototype.cook = function(){
/*do stuff*/
};
function Guacomole(){
}
Guacomole.prototype.spread = function(){
/*do stuff*/
};
extend(Taco.prototype, Beans.prototype);
console.log(Taco);
By using the extend function to implement the mixin pattern we created references to the super prototype methods.
Also notice that we don't inherit a constructor with the mixin
Since we're adding methods to the objects existing prototype, without Object.create() to assign a new prototype object, the constructor remains intact.
var canFly = function() {
this.price = 9.99;
this.takeOff = function() {
//fly baby
};
return this;
};
var isSubmersible = function() {
this.oxygenTanks = 4;
this.dive = function() {
//go deep
};
return this;
}
var Car = function(opts) {
this.wheels = 4;
if (opts.fly) {
canFly.call(Car.prototype);
}
if (opts.swim) {
isSubmersible.call(Car.prototype);
}
};
var flyingSubmaringCar = new Car({ fly : true, swim : true });
console.log(flyingSubmaringCar);
"A mixin should be a process not an object"
Although this achieves multiple inheritance best practice says:
"Something that adds behavior"
There are better, cleaner ways to inherit properties from another class thanks to ES6's Object.assign() method
We can use this to extend our functions more easier than building an extend function to do this for us
Remember, this only works on browsers that support ES6 at the bare minimum
Older browsers that do not support ES5 will require the use of a polyfill
function Taco(){
}
Taco.prototype.eat = function(){
/*do stuff*/
};
function Beans(){
}
Beans.prototype.cook = function(){
/*do stuff*/
};
function Guacomole(){
}
Guacomole.prototype.spread = function(){
/*do stuff*/
};
Taco.prototype = Object.assign(Taco.prototype, Beans.prototype);
console.log(Taco);
We'll use the Object.assign() method to extend our Taco's prototype with the contents of Beans instead of using the old extend function!
If any object implements an interface it must provide certain behavior and properties
If you wanna be in the band, you gotta wear the makeup bro...
Easiest Way To Remember Interfaces
//we could define an interface for a Car class such that
//every car must have an engine and a color like this:
interface ICar{
engine: string;
color: string;
}
//The Car class adheres to the interface ICar because it implements ICar
class Car implements ICar {
constructor (public engine: string, public color: string) {
}
}
//Create a new instance of a car and fulfills all requirements of the ICar interface 'contract'
var hondaAccord = new Car('V6', 'green');
alert(hondaAccord.engine);
Remember an interface is "just a contract".
By abiding by the contract your object will implement all the requirements of the contract
class Car {
private _basePrice: number;
engine: IEngine;
constructor(options: IAutoOptions) {
this._basePrice = options.basePrice;
this.engine = options.engine;
}
drive() : number {
console.log('driving');
return 1000;
}
get price(): number {
return this._basePrice;
}
set price(value: number) {
this._basePrice = value;
}
}
Implementing interfaces on subclasses
interface IEngine {
start() : void;
stop() : void;
}
interface IAutoOptions {
engine: IEngine;
basePrice: number;
}
interface ICanFly {
altitude: number;
fly() : void;
}
class FlyingEngine implements IEngine {
start() : void { }
stop() : void { }
}
class FlyingCar extends Car implements ICanFly {
altitude: number;
constructor(options: IAutoOptions){
super(options);
this.altitude = 0;
};
fly() : void {
this.engine.start();
console.log('flying');
}
}
//Create a new flying car
var fc = new FlyingCar({basePrice: 1000,
engine: new FlyingEngine()})
alert(fc.price); //[Alert] 1000
class Bird implements ICanFly {
name: string;
altitude: number;
constructor (name: string){
this.name = name;
this.altitude = 100;
};
fly() : void {
console.log('flying');
}
}
var fc = new FlyingCar({basePrice: 1000, engine: new FlyingEngine()})
var tweety = new Bird('Tweety');
var polly = new Bird('Polly');
var flyingThings: Array<ICanFly> = [fc, tweety, polly];
for (var i=0; i< flyingThings.length; i++) {
alert(flyingThings[i].altitude);
}
Verifying type with implementations
By DevLeague Coding Bootcamp