Search code examples
javascriptoopobjectprototypal-inheritance

Inheritance in Object Oriented JavaScript


I have 3 objects, Science, Physics and Mathematics.

I want the last two object (Physics and Mathematics) to inherit the protoype properties of Science.

Yet I want both Mathematics & Physics to update the inherited properties and define theirs. This is done, but I keep getting undefined when I try to access the Science properties and method via an instance of Physics. What could be wrong with my code.

function log(elem) {
  return console.log(elem);
}
//create supertype => Science
function Science() {}

//define Science prototype props
Science.prototype = {
  constructor: Science,
  dificulty: "Variable",
  universal: true,
  type: "science",
  name: "science",
  hasSubFields() {
    return true;
  },
};

//create 2 sub fields : Mathematics and Physics to inherit props from Science
function Mathematics(subField) {
  this.subField = subField;
}
function Physics() {}

//let mathematics & Physics inherit science props
Mathematics.prototype = 
Object.create(Science.prototype);
Physics.prototype = 
Object.create(Science.prototype);
Physics.prototype.constructor = Physics;

//over write Mathematics inherited props and physics
Mathematics.prototype = {
  constructor: Mathematics,
  name: "Mathematics",
  type: "Pure and applied Science",
};

Physics.prototype = {
  name: "Physics",
  dificulty: "80%",
  type: "Physical Science",
  subFields: ["Electricity", "Mechanics", "Sound", "Optics", "Waves"],
};

//make instance of Physics
let mechanics = new Physics();
mechanics.name = "mechanics";
mechanics.subFields = ["linear", "force", "force fileds"];

log(mechanics.universal);


Solution

  • Physics.prototype = new Science();
    
    //...
    
    Physics.prototype = {
      name: "Physics",
      dificulty: "80%",
      type: "Physical Science",
      subFields: ["Electricity", "Mechanics", "Sound", "Optics", "Waves"],
    };
    

    This second line is overwriting the first one. Once the code is done, the prototype is just the new object. There is no longer any relationship to Science, and thus no universal property to inherit.

    Instead of replacing prototype, you need to add to it:

    Physics.prototype = new Science();
    
    //...
    
    Physics.prototype.name = "Physics";
    Physics.prototype.dificulty = "80%";
    Physics.prototype.subFields = "Physical Science";
    Physics.prototype.name = ["Electricity", "Mechanics", "Sound", "Optics", "Waves"];
    

    Or:

    Physics.prototype = new Science();
    
    //...
    
    Object.assign(Physics.prototype, {
      name: "Physics",
      dificulty: "80%",
      type: "Physical Science",
      subFields: ["Electricity", "Mechanics", "Sound", "Optics", "Waves"],
    });
    

    Mathematics will need similar changes.

    function log(elem) {
      return console.log(elem);
    }
    //create supertype => Science
    function Science() {}
    
    //define Science prototype props
    Science.prototype = {
      constructor: Science,
      dificulty: "Variable",
      universal: true,
      type: "science",
      name: "science",
      hasSubFields() {
        return true;
      },
    };
    
    //create 2 sub fields : Mathematics and Physics to inherit props from Science
    function Mathematics(subField) {
      this.subField = subField;
    }
    function Physics() {}
    
    //let mathematics & Physics inherit science props
    Mathematics.prototype = Object.create(Science.prototype);
    Physics.prototype = Object.create(Science.prototype);
    Physics.prototype.constructor = Physics;
    
    //over write Mathematics inherited props and physics
    Object.assign(Mathematics.prototype, {
      constructor: Mathematics,
      name: "Mathematics",
      type: "Pure and applied Science",
    });
    
    Object.assign(Physics.prototype, {
      name: "Physics",
      dificulty: "80%",
      type: "Physical Science",
      subFields: ["Electricity", "Mechanics", "Sound", "Optics", "Waves"],
    })
    
    //make instance of Physics
    let mechanics = new Physics();
    mechanics.name = "mechanics";
    mechanics.subFields = ["linear", "force", "force fileds"];
    
    log(mechanics.universal);