Dónal
Dónal

Reputation: 187399

calling parent implementations of privileged functions

I have an inheritance relationship between two JavaScript classes1

RealTimeChart = function(chartAttributes) {

    var chart = new FusionCharts(chartAttributes);

    this.appendData = function(data) {
        chart.feedData(data);
    }
};

RealTimeGauge = function(chartAttributes) {
    chartAttributes.type = 'AngularGauge';

    // call parent constructor
    RealTimeChart.call(this, chartAttributes);
};

// inherit from RealTimeChart
RealTimeGauge.prototype = Object.create(RealTimeChart.prototype);

In RealTimeGauge I would like to override appendData(). The implementation of this function in RealTimeGauge needs to call the parent implementation, is this possible?

It's relatively straightforward to do this if I change appendData to a prototype function, e.g.

// parent class
RealTimeChart.prototype.appendData = function(data) {
    this.chart.feedData(data);
};

// child class
RealTimeGauge.prototype.appendData = function(data) {

    console.log("doing custom stuff...");

    // call the parent function to add the data to the chart
    RealTimeChart.prototype.appendData.call(this, data);
};

However, if I make appendData a prototype function rather than a privileged function, I also have to make chart a public property, which I'd rather not do. Is it possible to call the parent implementation of appendData form RealTimeGauge if it's a privileged function?

  1. I know they're not really classes, but I don't know of a better name for them

Upvotes: 3

Views: 77

Answers (2)

Hugo Wood
Hugo Wood

Reputation: 2270

To avoid this issue altogether, you could drop inheritance, and go for composition.

RealTimeChart = function(chartAttributes) {
    var chart = new FusionCharts(chartAttributes);
    this.appendData = function(data) {
        chart.feedData(data);
    };
};

RealTimeGauge = function (realTimeChart) {
    this.appendData = function (data) {
        console.log("doing custom stuff...");
        realTimeChart.appendData(data);
    };
};

new RealTimeGauge(new RealTimeChart({}));

Using composition results in simpler, more modular code. As you can see in the above code, RealTimeGauge only depends on the interface of RealTimeChart, not RealTimeChart itself, like in your original code. This means that you can substitute anything that has the same interface. The 2 'classes' are now decoupled. At what price? Less code that's more readable. You could go even further and decouple RealTimeChart from FusionCharts in the same way.

Upvotes: -1

salezica
salezica

Reputation: 77029

In the child constructor, after the calling the super constructor, this holds the priviledged function as an own property.

You can reassign this to a temporary variable and create the wrapping function that will replace super's implementation:

Parent = function() {
    var x = 1;

    this.work = function(y) {
        console.log(x + y);
    }
};

Child = function() {
    Parent.call(this);

    var super_work = this.work

    this.work = function(y) {
        super_work(y + 10); 
    }
};

Child.prototype = Object.create(Parent.prototype);

Let's give it a try:

p = new Parent()
p.work(1) # prints 2

c = new Child()
c.work(1) # prints 12

Upvotes: 2

Related Questions