【问题标题】:Workaround for calling private method in baseclass from subclass in JavaScript从 JavaScript 中的子类调用基类中的私有方法的解决方法
【发布时间】:2011-06-23 11:34:20
【问题描述】:
base = function () {
  this.A = function () {
    this.B();
  }
  this.B = function () {} // ABSTRACT!
  var E = function () {
    alert('I am E');
  }
}

sub = function () {
  this.B = function () {
    alert('I am B');
  }
  this.D = function () {
    E();
  }
}

sub.prototype = new base();

情况一:

(new sub()).D();

正如预期的那样,这不起作用,因为 D 和 E 处于不同的闭包中。我想保持 E 私有,因为它永远不应该被直接调用(即在一个实例上)。我理解不允许访问 E 的原因是为了确保封装,但我该怎么办?我唯一的两个选择似乎是使其具有特权(就像我说的那样,我反对,因为它允许在实例上调用它)或 手动将其复制到我的每个子类中作为私有方法(这不是一个解决方案)。

情况2:

(new sub()).A();

当我解析原型链的更高层时,我是否会在下一个函数调用时“重置”/从末尾开始?
是的。

【问题讨论】:

  • 你说“E”永远不应该被直接调用,但是那个函数“D”试图直接调用它......因此不清楚你想要什么。您是否试图模拟某些继承系统称为从子类到非公共基类方法的“受保护”访问的关系?
  • 这不仅仅是受保护的访问。我不希望在实例上调用该方法,只从其他方法中调用。在 javascript 中,通常的方法是通过匿名函数将其设为私有。但正如我所展示的,这在这种情况下是行不通的。
  • 好吧——除了 Java“包”范围的一些变态之外,这通常是“受保护”对我的意义 :-) 但是基本的 JavaScript 范围实际上与继承没有任何关系,所以从这个意义上说,“基”和“子”实例之间的关系与任何其他两个函数范围之间的关系没有什么不同。
  • 嗯...所以我假设我所提议的内容不可能在 JavaScript 中实现是正确的吗?
  • 是的。在函数范围内声明的符号不能直接从外部范围访问。

标签: javascript oop class encapsulation prototype-programming


【解决方案1】:

我使用以下步骤在 JavaScript 中创建了一个具有私有和公共范围的类:

  1. 创建一个只有公共成员的普通原型链
  2. 使用方法本身的布尔集将公共方法标记为公共或私有成员为私有。 (访问function foo() {}; foo._private = true;
  3. 在“接口类”中实例化链
  4. 遍历链实例,在接口类上创建对其公共成员的引用
  5. 将这些引用重新绑定到链实例

这里有一些代码:

function BaseClass() {
  this.A = function A() {
    this.B();
  }
  this.B = function B() {}
  this.C = function C() {
    console.log('I am C');
  }
  this.C._private = true;
}

function Subclass() {
  this.D = function D() {
    this.C();
  }
  this.B = function B() {
    console.log('I am B');
  }
}
Subclass.prototype = new BaseClass();

function Interface() {

  var classScope = new Subclass();
  for ( var property in classScope ) {
    if ( !classScope[property]._private ) {
      this[property] = classScope[property].bind(classScope);
    }
  }
}

var classInstance = new Interface();
console.log(classInstance);
classInstance.A();
classInstance.B();
classInstance.D();

要查看输出,请查看this code pen

通过稍微清理一下代码以使每个表达式的目的更加清晰,checkout this code pen

注意function C() {}function Interface() {} 完全封装,但(new Interface()).D() 仍然可以访问它。

另外,请注意(new Interface()).A() 调用Subclass#B()

【讨论】:

    猜你喜欢
    • 2010-12-05
    • 2011-01-05
    • 2010-09-30
    • 2011-01-22
    • 2020-09-11
    • 2011-02-11
    • 2015-01-04
    • 1970-01-01
    • 2014-01-27
    相关资源
    最近更新 更多