Menu
Coddy logo textTech

Building objects

Part of the Object Oriented Programming section of Coddy's JavaScript journey — lesson 49 of 56.

Now that we understand the problems with deep inheritance and the "has-a" relationship, let's learn how to build objects by combining small, reusable components. This approach gives us maximum flexibility! 

The Basic Pattern:

// Step 1: Create small, focused components
class Engine {
  constructor(power) {
    this.power = power;
  }
  
  start() {
    console.log(`Engine (${this.power}HP) starting...`);
  }
}

class Wheels {
  constructor(count) {
    this.count = count;
  }
  
  rotate() {
    console.log(`${this.count} wheels rotating`);
  }
}
// Step 2: Build objects by combining components
class Car {
  constructor(brand, enginePower, wheelCount) {
    this.brand = brand;
    this.engine = new Engine(enginePower);    // HAS-AN engine
    this.wheels = new Wheels(wheelCount);     // HAS wheels
  }
  
  drive() {
    console.log(`${this.brand} is driving:`);
    this.engine.start();
    this.wheels.rotate();
  }
}
// Step 3: Use the composed object
const myCar = new Car('Toyota', 150, 4);
myCar.drive();
// Output:
// Toyota is driving:
// Engine (150HP) starting...
// 4 wheels rotating

The Real Power: Mix and Match Components:

// More specialized components
class TurboCharger {
  boost() {
    console.log('Turbo engaged! Extra power!');
  }
}

class SoundSystem {
  constructor(type) {
    this.type = type;
  }
  
  playMusic() {
    console.log(`Playing music on ${this.type} sound system`);
  }
}
// Build different cars with different combinations
class SportsCar {
  constructor(brand) {
    this.brand = brand;
    this.engine = new Engine(300);
    this.wheels = new Wheels(4);
    this.turbo = new TurboCharger();      // Sports car gets turbo
    this.soundSystem = new SoundSystem('Premium'); // And good sound
  }
  
  raceMode() {
    console.log(`${this.brand} in race mode:`);
    this.engine.start();
    this.turbo.boost();
    this.wheels.rotate();
    console.log('VROOOOM!');
  }
  
  cruise() {
    console.log(`${this.brand} cruising:`);
    this.engine.start();
    this.wheels.rotate();
    this.soundSystem.playMusic();
  }
}
class EconomyCar {
  constructor(brand) {
    this.brand = brand;
    this.engine = new Engine(100);
    this.wheels = new Wheels(4);
    // No turbo for economy car
    this.soundSystem = new SoundSystem('Basic'); // Basic sound only
  }
  
  drive() {
    console.log(`${this.brand} driving efficiently:`);
    this.engine.start();
    this.wheels.rotate();
    this.soundSystem.playMusic();
  }
}
// See how flexible this is!
const ferrari = new SportsCar('Ferrari');
const honda = new EconomyCar('Honda');

ferrari.raceMode();  // Has turbo boost!
ferrari.cruise();    // Has premium sound!

honda.drive();       // Just basic features

This approach gives you flexibility to mix and match behaviors without complex inheritance chains!

challenge icon

Challenge

Complete the SmartBulb methods in the SmartBulb.js file.

  1. Implement the activate() method to turn on the light.
  2. Implement the adjustBrightness() method to set the brightness and log exactly: Brightness set to ${this.brightness.level}%

Cheat sheet

Objects can be built by combining small, reusable components instead of using deep inheritance. This is called composition and follows the "has-a" relationship.

Basic composition pattern:

// Step 1: Create small, focused components
class Engine {
  constructor(power) {
    this.power = power;
  }
  
  start() {
    console.log(`Engine (${this.power}HP) starting...`);
  }
}

// Step 2: Build objects by combining components
class Car {
  constructor(brand, enginePower) {
    this.brand = brand;
    this.engine = new Engine(enginePower);  // HAS-AN engine
  }
  
  drive() {
    this.engine.start();
  }
}

Mix and match components for flexibility:

class TurboCharger {
  boost() {
    console.log('Turbo engaged!');
  }
}

class SportsCar {
  constructor(brand) {
    this.brand = brand;
    this.engine = new Engine(300);
    this.turbo = new TurboCharger();  // Add turbo component
  }
  
  raceMode() {
    this.engine.start();
    this.turbo.boost();
  }
}

class EconomyCar {
  constructor(brand) {
    this.brand = brand;
    this.engine = new Engine(100);
    // No turbo component
  }
}

Composition allows you to build objects with different combinations of features without complex inheritance chains.

Try it yourself

import { SmartBulb } from './SmartBulb.js';

const bedroomLight = new SmartBulb('warm white');

console.log('1. Activating light:');
bedroomLight.activate();

console.log('\n2. Adjusting brightness:');
bedroomLight.adjustBrightness(75);
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming