Javascript:从基类继承方法并返回子类的私有变量

时间:2013-08-02 15:25:43

标签: javascript oop inheritance

我定义了以下BaseClass:

function BaseClass (arg1,arg2,arg3) {
    //constructor code here then - 
    var privateVar = 7500;
    this.getPrivateVar = function() { return privateVar; };
}

我希望有以下子类允许更改privateVar,如下所示:

function SubClass (arg1,arg2,arg3,privateVar) {
    //constructor code here then - 
    var privateVar = privateVar;
}
SubClass.prototype = new BaseClass();

现在我希望SubClass继承getPrivateVar方法。但是,当我尝试这个时,它总是返回7500,它是BaseClass中的值而不是privateVar的值。

换句话说,是否可以继承BaseClass的公共方法,但是它们中的任何引用都引用了SubClass的属性?我该怎么做?


通过事物的声音,这是不可能的。我的想法是为我的学生代码自动化代码检查器(我辅导孩子),但我只需要找到另一种方式。不管怎样,谢谢。

6 个答案:

答案 0 :(得分:3)

您正在将Javascript对象模型与不互操作*的范围变量混合使用。

继承执行SubClass.prototype = new BaseClass();的习惯用语只有在你自然地使用原型和构造函数时才有效:

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;

在您认为任何人都可以通过编写_来访问该属性之前,我可以争辩说任何人都可以通过使用反射来访问Java,PHP或C#中的任何私有。或者在Ruby中使用instance_evalsend等等。无论如何它都在你的手中。


*根据实施情况使用范围变量时,无或大部分都不起作用:

  • Enumerability
  • 可写性
  • 一流的访问者
  • 密封性,冻结性和延伸状态
  • 通过getPropertyNames或键进行反思
  • instanceof operator
  • 通用方法
  • 继承

答案 1 :(得分:2)

您定义privateVar的方式使其成为BaseClass“构造函数”范围内的局部变量。像Neal说的那样,你不能从任何继承的类继承或“看”它。 您可以使用像Neal所说的闭包(但这可能是内存过度杀伤,具体取决于您的使用情况),或者使变量成为实例变量:

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

答案 2 :(得分:2)

拥有private variable的想法是不应该在声明范围之外访问。但是,有几种方法可以实现您的目标。例如,您可以在privateVar dynamic:

中设置默认值BaseClass
function BaseClass(arg1,arg2,arg3) {
    var privateVar = BaseClass.privateVar;

    this.getPrivateVar = function () {
        return privateVar;
    };
}

BaseClass.privateVar = 7500;

现在您可以按如下方式创建SubClass

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

现在您只需创建一个SubClass的实例:http://jsfiddle.net/Pytkj/

答案 3 :(得分:0)

privateVarBaseClass的局部变量。 不能由子类继承或更改。

您可以将父类和子类封装在同一范围内,如下所示:

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

答案 4 :(得分:0)

你不会。即使你可以,该财产也不能被称为“私人”。也许“受到保护”。

缺少不同访问级别的语言只使用公共属性和某种命名约定(比如调用它们__semiPrivateVar)。

有一些不同的解决方案,但它们在OO方面并不是真正可以描述的(你真正拥有的不是类和属性,而是构造函数,范围和变量)。

答案 5 :(得分:0)

  

继承BaseClass的公共方法但是它们中的任何引用都引用了SubClass的属性?

不,那是不可能的。在BaseClass构造函数范围内创建的方法将始终引用该范围内的变量,您无法对其进行更改。它是变量,而不是对象的属性

但是,你做的继承是错误的。您有一个BaseClass 实例,您可以从中继承所有SubClass实例,并与之共享getPrivateVar方法。给他们一个自己的!为此,您可以在子实例上应用父构造函数,创建新的闭包范围和新方法。并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);