最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

oop - Javascript: Inherit method from base class and return the subclass's private variable - Stack Overflow

programmeradmin3浏览0评论

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.

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.

Share Improve this question edited Aug 8, 2013 at 21:11 marisbest2 asked Aug 2, 2013 at 15:25 marisbest2marisbest2 1,3562 gold badges19 silver badges31 bronze badges
Add a ment  | 

6 Answers 6

Reset to default 3

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:

  • Enumerability
  • Writability
  • First-class Accessors
  • Sealedness, Frozedness and state of Extension
  • Reflection through getPropertyNames or keys
  • instanceof operator
  • Generic methods
  • Inheritance

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());

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/Pytkj/

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;
})();

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).

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);
发布评论

评论列表(0)

  1. 暂无评论