Обходной путь для вызова частного метода в базовом классе из подкласса в JavaScript - PullRequest
1 голос
/ 23 июня 2011
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();

Ситуация 1:

(new sub()).D();

Это не работает, как ожидалось, так как D и E находятся в разных замыканиях.Я хочу сохранить E закрытым, так как он никогда не должен вызываться напрямую (например, в экземпляре).Я понимаю, что причина отсутствия доступа к E заключается в обеспечении инкапсуляции, но что я могу сделать?Похоже, у меня есть только два варианта: сделать его привилегированным (что, как я уже сказал, я против, поскольку он позволяет вызывать его в экземпляре), или вручную скопировать в каждый из моих подклассовчастный метод (который не является чем-то вроде решения).

Ситуация 2:

(new sub()).A();

Когда я решаю выше цепь прототипов«сбросить» / начать с конца при следующем вызове функции?
Да.

1 Ответ

0 голосов
/ 21 февраля 2015

Я использовал следующие шаги для создания класса с частной и публичной областью действия в JavaScript:

  1. Создать нормальную цепочку прототипов только с открытыми членами
  2. Либо помечайте открытые методы как открытые, так и закрытые, как частные, используя логический набор самого метода. (vis. 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();

Чтобы увидеть вывод, проверьте этот код пера .

Чтобы увидеть, как код немного подправлен, чтобы прояснить назначение каждого выражения, проверьте этот код pen .

Обратите внимание, что function C() {} полностью инкапсулирован function Interface() {}, но (new Interface()).D() все еще имеет к нему доступ.

Также обратите внимание, что (new Interface()).A() вызывает Subclass#B().

...