How can I go about making a child class override a privileged method of a base class?
If its not possible, is there another way to achieve what I am trying to accomplish in the simple code example below?
I cannot convert the baseclass function parseXML() to public because it requires access to private variables
function BaseClass()
{
var map = {};
// I cannot make this function public BECAUSE it accesses & changes private variables
this.parseXML = function( key, value )
{
alert("BaseClass::parseXML()");
map[key] = value;
}
}
function ChildClass()
{
BaseClass.call(this);
this.parseXML = function( key, value, otherData )
{
alert("ChildClass()::parseXML()");
// How can I call the base class function parseXML()?
//this.parseXML(); // calls this function not the parent function
//MyClass.prototype.doStuff.call
BaseClass.prototype.parseXML.call(this, key, value); // fails
//BaseClass.prototype.parseXML(); // fails
// perform specialised actions here with otherData
}
}
ChildClass.prototype = new BaseClass;
var a = new ChildClass();
a.parseXML();
How can I go about making a child class override a privileged method of a base class?
If its not possible, is there another way to achieve what I am trying to accomplish in the simple code example below?
I cannot convert the baseclass function parseXML() to public because it requires access to private variables
function BaseClass()
{
var map = {};
// I cannot make this function public BECAUSE it accesses & changes private variables
this.parseXML = function( key, value )
{
alert("BaseClass::parseXML()");
map[key] = value;
}
}
function ChildClass()
{
BaseClass.call(this);
this.parseXML = function( key, value, otherData )
{
alert("ChildClass()::parseXML()");
// How can I call the base class function parseXML()?
//this.parseXML(); // calls this function not the parent function
//MyClass.prototype.doStuff.call
BaseClass.prototype.parseXML.call(this, key, value); // fails
//BaseClass.prototype.parseXML(); // fails
// perform specialised actions here with otherData
}
}
ChildClass.prototype = new BaseClass;
var a = new ChildClass();
a.parseXML();
Share
Improve this question
edited Mar 30, 2019 at 18:17
user4639281
asked Nov 7, 2011 at 0:16
sazrsazr
25.9k70 gold badges211 silver badges385 bronze badges
3
- possible duplicate of Possible to override a base classes privileged function? ... please edit your original question instead. – Felix Kling Commented Nov 7, 2011 at 0:23
- 2 Suggestion: Don't try to force method visibility into JavaScript. It is not designed to have private and protected methods. Document your code properly. Mark this method as private in the comment. If someone uses the method anyway and therefore breaks his code when he uses your library -> his problem. – Felix Kling Commented Nov 7, 2011 at 0:43
- possible duplicate of Calling base method using javascript prototype – outis Commented Nov 7, 2011 at 6:24
2 Answers
Reset to default 16function BaseClass() {
var map = {};
this.parseXML = function(key, value) {
alert("BaseClass::parseXML()");
map[key] = value;
}
}
function ChildClass() {
BaseClass.call(this);
var parseXML = this.parseXML;
this.parseXML = function(key, value, otherData) {
alert("ChildClass()::parseXML()");
parseXML.call(this, key, value);
}
}
ChildClass.prototype = new BaseClass;
var a = new ChildClass();
a.parseXML();
Live Example
Basically you cache the privileged method (which is only defined on the object) and then call it inside the new function you assign to the privileged method name.
However a more elegant solution would be:
function BaseClass() {
this._map = {};
};
BaseClass.prototype.parseXML = function(key, value) {
alert("BaseClass::parseXML()");
this._map[key] = value;
}
function ChildClass() {
BaseClass.call(this);
}
ChildClass.prototype = Object.create(BaseClass.prototype);
ChildClass.prototype.parseXML = function(key, value, otherData) {
alert("ChildClass()::parseXML()");
BaseClass.prototype.parseXML.call(this, key, value);
}
var a = new ChildClass();
a.parseXML();
Live Example
Also bonus implementation using pd
IMO, you need to use a Javascript library like Ext Js to simplify this task. Anyway, the following example illustrates how you can write some helper methods. It's a part of an unreleased open source project that I'm working on.
var JWObject = (function () {
var jwobj = function (){};
jwobj.prototype = { };
return jwobj;
})();
var Prototype = (function () {
var scopeQueue = [ window ];
return {
beginScope: function (namespace) {
var parts = namespace.split('.');
for (var i = 0; i < parts.length; i++) {
var name = parts[i],
parent = this.getScope(),
part = parent[name];
if (part && !part.__namespace) {
throw Error('/* ERROR MESSAGE */');
}
scopeQueue.push(parent[name] = (part || { __namespace: true }));
}
},
endScope: function () {
if (scopeQueue.length > 1) {
scopeQueue.pop();
}
},
getScope: function () {
return scopeQueue.pick();
},
define: function (name, members) {
var scope = this.getScope();
if (scope[name]) {
throw Error('The prototype already exist.');
}
this.extend(members, {
scope: scope,
extend: JWObject,
statics: {}
});
// Getting constructor
var ctor = (members.constructor === Object) ? function() { } : members.constructor;
delete members.constructor;
if (typeof members.extend === 'string') {
members.extend = scope[members.extend];
}
if (!members.extend) {
throw Error('The base class is not specified.');
}
// Deriving from parent type
ctor.prototype = new members.extend();
members.super = members.extend.prototype;
delete members.extend;
members.statics.__class = true;
this.extend(ctor, members.statics, true);
delete members.statics;
// Adding new members
this.extend(ctor.prototype, members, true);
// Adding and returning the created prototype
return scope[name] = ctor;
},
extend: function (expando, members, override) {
for (var m in members) {
if (override || !expando[m]) {
expando[m] = members[m];
}
}
}
};
})();
Prototype.extend(Array.prototype, {
pick: function() {
return this[this.length - 1];
}
});
Here is the result:
Prototype.beginScope('Sample');
/**
* Prototype: Sample.Plugin
*/
Prototype.define('Plugin', {
init: function() {
alert('init!');
}
});
Prototype.beginScope('Extension');
/**
* Prototype: Sample.Extensions.Plugin
* Extend : Sample.Plugin
*/
Prototype.define('Foo', {
extend: Sample.Plugin,
init: function() {
this.super.init.call(this);
alert('child: init!');
},
fun: function() {
this.init();
},
statics: {
create: function() {
return new Sample.Extension.Foo();
}
}
});
Prototype.endScope();
Prototype.endScope();
As you can see in the preceding code, the Prototype object provides some functionality to defining a namespace (Prototype.beginScope
, Prototype.endScope
and Prototype.getScope
) or defining a prototype (Prototype.define
).
You can inherit a prototype from another using extend like java.
Prototype.define('Foo', {
extend: Sample.Plugin,
Or call the base class method as follows:
init: function() {
this.super.init.call(this);
Also, every prototype you define with above code will be derived from JWObject by default.