Reputation: 1356
I have the following BaseClass defined:
function BaseClass (arg1,arg2,arg3) {
//constructor code here then -
var privateVar = 7500;
this.getPrivateVar = function() { return privateVar; };
}
I want to have the following subclass which allows changing privateVar like so:
function SubClass (arg1,arg2,arg3,privateVar) {
//constructor code here then -
var privateVar = privateVar;
}
SubClass.prototype = new BaseClass();
Now I want SubClass to inherit the getPrivateVar
method. However, when I try this, it always returns 7500
which is the value in the BaseClass and not the value of privateVar
.
In other words, is it possible to inherit a BaseClass's public methods but have any references in them refer to the SubClass's properties? And how would I do that?
By the sound of things, it's impossible. The idea was to automate a code-checker for my students code (I tutor kids) but I'll just have to find another way. Thanks anyway.
Upvotes: 1
Views: 3471
Reputation: 74204
The idea of having a private variable is that is should not be accessible outside of the scope in which is was declared. However there are a few ways to achieve what you wish to do. For example, you could make the default value of privateVar
in BaseClass
dynamic:
function BaseClass(arg1,arg2,arg3) {
var privateVar = BaseClass.privateVar;
this.getPrivateVar = function () {
return privateVar;
};
}
BaseClass.privateVar = 7500;
Now you can create SubClass
as follows:
function SubClass(arg1, arg2, arg3, privateVar) {
var args = Array.prototype.slice.call(arguments, 0, 3); // the first 3 args
var defaultPrivateVar = BaseClass.privateVar; // save the old value
BaseClass.privateVar = privateVar; // set a new default
BaseClass.call(this, args); // call super
BaseClass.privateVar = defaultPrivateVar; // restore old value
}
SubClass.prototype = Object.create(BaseClass.prototype); // inherit new way
Now all you need to do is simply create an instance of SubClass
: http://jsfiddle.net/Pytkj/
Upvotes: 2
Reputation: 664297
inherit a BaseClass's public methods but have any references in them refer to the SubClass's properties?
No, that's impossible. The method created inside the BaseClass
constructor scope will always reference the variables from that scope, you cannot change it. It's a variable, not a property of the object.
However, you're doing the inheritance wrong. You have a BaseClass
instance from which you inherit and with which all SubClass
instances will share their getPrivateVar
method. Get them an own one! To do so, you can apply the parent constructor on the child instance, creating a new closure scope and a new method. And don't use new
!
function SubClass (arg1,arg2,arg3) {
BaseClass.call(this);
}
// or, if you need a reference to the variable:
function SubClass (arg1,arg2,arg3) {
// you have to create it on your own
var privateVar = arguments[3]; // or use a formal parameter
// and create `getPrivateVar` yourself
this.getPrivateVar = function() { return privateVar; };
}
SubClass.prototype = Object.create(BaseClass.prototype);
Upvotes: 0
Reputation: 140210
You are mixing Javascript object model with scoped variables which do not interoperate*.
The inherits idiom of doing SubClass.prototype = new BaseClass();
only works when you are using prototypes and constructors naturally:
function BaseClass(arg1, arg2, arg3) {
this._privateVar = 7500;
}
BaseClass.prototype.getPrivateVar = function() {
return this._privateVar;
};
function SubClass(arg1, arg2, arg3, privateVar) {
}
SubClass.prototype = new BaseClass();
//Better way to do it is
//SubClass.prototype = Object.create(BaseClass.prototype);
SubClass.prototype.constructor = SubClass;
Before you argue that anyone can access the property by just writing _
, I could argue back that anyone can access any private in Java, PHP or C# by using reflection. Or using instance_eval
or send
in Ruby and so on. So it's out of your hands anyway.
*None or most of these don't work when you use scoped variables depending on implementation:
Upvotes: 3
Reputation: 12495
You would not. And even if you could, the property could not be called "private" any more. Maybe "protected".
Languages that lack different access levels just use public attributes and some sort of a naming convention (like calling them __semiPrivateVar).
There are some different solutions, but they are not really describable in terms of OO (what you really have are not classes and attributes but constructors, scopes and variables).
Upvotes: 0
Reputation: 1295
The way you defined privateVar makes it a local variable inside the scope of BaseClass "constructor". Like Neal said, you cannot inherit nor "see" it from any inherited class. You can use a closure like Neal said (but this can be a memory overkill depending on your usage context), or make the variable an instance variable:
function BaseClass (arg1,arg2,arg3) {
//constructor code here then -
this.privateVar = 7500;
this.getPrivateVar = function() { return this.privateVar; };
}
function SubClass (arg1,arg2,arg3,privateVar) {
//constructor code here then -
this.privateVar = privateVar;
}
SubClass.prototype = new BaseClass();
var subClass = new SubClass(1,2,3,4000);
console.log(subClass.getPrivateVar());
Upvotes: 2
Reputation: 146302
privateVar
is a local variable of BaseClass
. It cannot be inherited or changed by the subclass.
You can encapsulate the parent and subclass in the same scope like so:
(function(){
var privateVar = 7500;
function BaseClass (arg1,arg2,arg3) {
//constructor code here then -
this.getPrivateVar = function() { return privateVar; };
}
function SubClass (arg1,arg2,arg3,privateVar) {
//constructor code here then -
}
SubClass.prototype = new BaseClass();
return SubClass;
})();
Upvotes: 0