jgrant
jgrant

Reputation: 659

How do I augment a method from the superclass in javascript

I have a method in a base class that I want to keep in a subclass, but just add to it. I've found lots of stuff on augmenting classes and objects with properties and methods, but I can't find, or don't understand, how to just augment the method. The worst case scenario is that I would have to paste the entire method of the parent class into the subclass, but that seems like duplicate code... please help

function someObject (){
    this.someProperty = 1;
    this.incrementProperty = function incrementProperty(){   
        this.propertyOfSomeObject += 1;
    }
}

function newObject (){
    someObject.call(this);
    this.incrementProperty =  function incrementProperty(){
        //do everything the super class has for this property already
        return this.someProperty;
    }
}

var incrementer = new newObject;
alert (incrementer.incrementProperty()); //I want output to be 2

Upvotes: 2

Views: 630

Answers (4)

Aadit M Shah
Aadit M Shah

Reputation: 74204

I usually use the augment library to write classes in JavaScript. This is how I would rewrite your code using augment:

var Foo = Object.augment(function () {
    this.constructor = function () {
        this.someProperty = 1;
    };

    this.incrementProperty = function () {
        this.someProperty++;
    };
});

var Bar = Foo.augment(function (base) {
    this.constructor = function () {
        base.constructor.call(this);
    };

    this.incrementProperty = function () {
        base.incrementProperty.call(this);
        return this.someProperty;
    };
});

As you can see since Bar extends Foo it gets Foo.prototype as a parameter (which we call base). This allows you to easily call the base class constructor and incrementProperty functions. It also shows that the constructor itself is just another method defined on the prototype.

var bar = new Bar;

alert(bar.incrementProperty());

The output will be 2 as expected. See the demo for yourself: http://jsfiddle.net/47gmQ/

Upvotes: 1

HMR
HMR

Reputation: 39260

From this answer:

Overriding functions

Sometimes children need to extend parent functions.

You want the 'child' (=RussionMini) to do something extra. When RussionMini can call the Hamster code to do something and then do something extra you don't need to copy and paste Hamster code to RussionMini.

In the following example we assume that a Hamster can run 3km an hour but a Russion mini can only run half as fast. We can hard code 3/2 in RussionMini but if this value were to change we have multiple places in code where it needs changing. Here is how we use Hamster.prototype to get the parent (Hamster) speed.

// from goog.inherits in closure library
var inherits = function(childCtor, parentCtor) {
  function tempCtor() {};
  tempCtor.prototype = parentCtor.prototype;
  childCtor.prototype = new tempCtor();
  childCtor.prototype.constructor = childCtor;
};


var Hamster = function(name){
 if(name===undefined){
   throw new Error("Name cannot be undefined");
 }
 this.name=name;
}
Hamster.prototype.getSpeed=function(){
  return 3;
}
Hamster.prototype.run=function(){
  //Russionmini does not need to implement this function as
  //it will do exactly the same as it does for Hamster
  //But Russionmini does need to implement getSpeed as it
  //won't return the same as Hamster (see later in the code) 
  return "I am running at " + 
    this.getSpeed() + "km an hour.";
}

var RussionMini=function(name){
  Hamster.apply(this,arguments);
}
//call this before setting RussionMini prototypes
inherits(RussionMini,Hamster);

RussionMini.prototype.getSpeed=function(){
  return Hamster.prototype
    .getSpeed.call(this)/2;
}    

var betty=new RussionMini("Betty");
console.log(betty.run());//=I am running at 1.5km an hour.

Upvotes: 0

Andy Jones
Andy Jones

Reputation: 6275

// parent object
function someObject () {
    this.someProperty = 1;
}

// add incrementProperty to the prototype so you're not creating a new function
// every time you instantiate the object
someObject.prototype.incrementProperty = function() {   
  this.someProperty += 1;
  return this.someProperty;
}

// child object
function newObject () {
    // we could do useful work here
}

// setup new object as a child class of someObject
newObject.prototype = new someObject();
// this allows us to use "parent" to call someObject's functions
newObject.prototype.parent = someObject.prototype;
// make sure the constructor points to the right place (not someObject)
newObject.constructor = newObject;

newObject.prototype.incrementProperty = function() {
    // do everything the super class has for this property already
    this.parent.incrementProperty.call(this);
    return this.someProperty;
}

var incrementer = new newObject();
alert (incrementer.incrementProperty()); // I want output to be 2

See: http://jsfiddle.net/J7RhA/

Upvotes: 4

alexgirao
alexgirao

Reputation: 895

this should do, you have to use prototype to have a real concept of oo with javascript

function someObject (){
    this.someProperty = 1;
    this.propertyOfSomeObject = 0;
    this.incrementProperty = function incrementProperty(){   
        this.propertyOfSomeObject += 1;
        return this.propertyOfSomeObject;
    }
}

function newObject (){
    someObject.call(this);
    this.incrementProperty =  function incrementProperty(){
        this.__super__.incrementProperty.apply(this);
        return this.propertyOfSomeObject + 1;
    }
}

newObject.prototype = new someObject()
newObject.prototype.__super__ = newObject.prototype

var incrementer = new newObject();
alert(incrementer.incrementProperty()); //I want output to be 2

experiment removing incrementProperty from newObject and it will return 1

Upvotes: 1

Related Questions