Skip to content

Instantly share code, notes, and snippets.

@jeffschwartz
Created February 16, 2013 18:14
Show Gist options
  • Save jeffschwartz/4967997 to your computer and use it in GitHub Desktop.
Save jeffschwartz/4967997 to your computer and use it in GitHub Desktop.
Demonstrates how to use object composition instead of inheritance to create rich objects in JavaScript.
/*
* Demonstrates using object composition
* instead of inheritance.
*
* Using inheritance a car would inherit from vehicle
* and we'd have to fashion that relationship using
* either pseudo classical inheritance or prototypal
* inheritance. By using composition to create
* objects you can avoid the hassles of using
* either form of inheritance.
*/
(function () {
"use strict";
/// for utility
var show = function ( output ) {
if ( typeof output != 'undefined' ) {
console.log( output );
}
};
/// composes a vehicle object
var makeVehicle = function ( spec ) {
var vehicle = {};
if ( typeof spec.type === 'undefined' ) {
throw "makeVehicle() requires spec.type to be defined"
}
spec.sound = spec.sound || "this vehicle doesn't have a horn";
spec.model = spec.model || '';
spec.mileage = spec.mileage || 0;
var getType = function () {
return spec.type;
};
var getSound = function () {
return spec.sound;
};
var getModel = function () {
return spec.model;
};
var getMileage = function () {
return spec.mileage;
};
var honk = function ( n ) {
if ( typeof n === 'number' ) {
var sound = getSound();
while ( n ) {
show( (sound + " " + sound) );
n -= 1;
}
}
};
vehicle.getType = getType;
vehicle.getSound = getSound;
vehicle.getModel = getModel;
vehicle.getMileage = getMileage;
vehicle.honk = honk;
return vehicle;
};
/// composes a car object
var makeCar = function ( spec ) {
var car;
if ( typeof spec.model === 'undefined' ) {
throw 'makecar() expects spec.model to be defined';
}
spec.type = 'car';
spec.sound = 'Beep!';
spec.bodyType = spec.bodyType || 'sedan';
spec.engineType = spec.engineType || 'gasoline';
spec.numberOfWheels = 4;
var getBodyType = function () {
return spec.bodyType;
};
var getNumberOfWheels = function () {
return spec.numberOfWheels;
};
var getEngineType = function () {
return spec.engineType;
};
car = makeVehicle( spec );
car.getBodyType = getBodyType;
car.getNumberOfWheels = getNumberOfWheels;
car.getEngineType = getEngineType;
return car;
};
/// make a car using composition
var car1 = makeCar( {model : 'Civic', engineType : 'hybrid', mileage : 42000 } );
/// Take a look at the car object in your browser's console
/// Notice how the car object now has methods contributed
/// by both makeVehicle and makeCar, yet we only called
/// makeCar. Internally, makeCar calls makeVehicle.
///
/// In OO terms 'a car is a vehicle' and our
/// car object reflects that by its composites.
///
show( car1 );
/// use composites contributed from makeVehicle
show( car1.getType() );
show( car1.getSound() );
show( car1.getModel() );
show( car1.getMileage() );
show( car1.honk( 2 ) );
/// use composites contributed from makeCar
show( car1.getBodyType() );
show( car1.getNumberOfWheels() );
show( car1.getEngineType() );
/// Exercise - using this 'library' create a motorcycle
/// and use its composites to get at its information in
/// the same way I did above for a car.
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment