简体   繁体   English

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

[英]Javascript: Inherit method from base class and return the subclass's private variable

I have the following BaseClass defined: 我定义了以下BaseClass:

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: 我想拥有以下允许更改privateVar的子类:

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. 现在,我希望SubClass继承getPrivateVar方法。 However, when I try this, it always returns 7500 which is the value in the BaseClass and not the value of privateVar . 但是,当我尝试此操作时,它总是返回7500 ,这是BaseClass中的值,而不是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? 换句话说,是否可以继承BaseClass的公共方法,但是其中有任何引用引用SubClass的属性? 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. 不管怎么说,还是要谢谢你。

You are mixing Javascript object model with scoped variables which do not interoperate*. 您正在将Javascript对象模型与不能互操作的作用域变量混合*。

The inherits idiom of doing SubClass.prototype = new BaseClass(); 执行SubClass.prototype = new BaseClass();的继承习惯用法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. 在您认为任何人都可以通过编写_来访问该属性之前,我可以反驳说任何人都可以通过使用反射来访问Java,PHP或C#中的任何private。 Or using instance_eval or send in Ruby and so on. 或使用instance_eval或在Ruby中send等等。 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 通过getPropertyNames或键进行反射
  • instanceof operator 运算符实例
  • Generic methods 通用方法
  • Inheritance 遗产

The way you defined privateVar makes it a local variable inside the scope of BaseClass "constructor". 定义privateVar的方式使其成为BaseClass“构造函数”范围内的局部变量。 Like Neal said, you cannot inherit nor "see" it from any inherited class. 就像Neal所说的那样,您不能从任何继承的类继承或“看到”它。 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: 您可以像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());

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: 例如,您可以在BaseClass privateVar的默认值动态化:

function BaseClass(arg1,arg2,arg3) {
    var privateVar = BaseClass.privateVar;

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

BaseClass.privateVar = 7500;

Now you can create SubClass as follows: 现在,您可以按以下方式创建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

Now all you need to do is simply create an instance of SubClass : http://jsfiddle.net/Pytkj/ 现在,您只需要简单地创建SubClass的实例即可: http : //jsfiddle.net/Pytkj/

privateVar is a local variable of BaseClass . privateVarBaseClass的局部变量。 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). 缺乏不同访问级别的语言仅使用公共属性和某种命名约定(例如称它们为__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). 有一些不同的解决方案,但是它们并不是真正按照OO描述的(您真正拥有的不是类和属性,而是构造函数,范围和变量)。

inherit a BaseClass's public methods but have any references in them refer to the SubClass's properties? 继承BaseClass的公共方法,但是其中有任何引用引用SubClass的属性吗?

No, that's impossible. 不,那是不可能的。 The method created inside the BaseClass constructor scope will always reference the variables from that scope, you cannot change it. BaseClass构造函数作用域内创建的方法将始终引用该作用域中的变量,您不能对其进行更改。 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. 您有一个继承自其的BaseClass 实例 ,所有SubClass实例将与它们共享其getPrivateVar方法。 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 ! 并且不要使用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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM