Закрытые члены при расширении класса с помощью ExtJS

Я провел небольшое исследование на форуме ExtJS относительно приватных методов и полей внутри расширенного класса и не смог не найти никакого реального ответа на это.

И когда я говорю расширенный класс, я имею в виду что-то вроде этого:

Ext.ux.MyExtendedClass = Ext.extend(Ext.util.Observable, {
    publicVar1: 'Variable visible from outside this class',
    constructor: function(config) { this.addEvents("fired"); this.listeners = config.listeners; }, // to show that I need to use the base class
    publicMethod1: function() { return 'Method which can be called form everywhere'; },
    publicMethod2: function() { return this.publicMethod1() + ' and ' + this.publicVar1; } // to show how to access the members from inside another member
});

Проблема в том, что все публично. Итак, как мне добавить новую переменную или метод в область MyExtendedClass, к которой нельзя получить доступ извне, но к которой можно получить доступ с помощью общедоступных методов?


person Mariano Desanze    schedule 28.04.2010    source источник


Ответы (3)


Я использую что-то вроде следующего.

  var toolbarClass = Ext.extend( Ext.Container,
  {
    /**
     * constructor (public)
     */
    constructor: function( config )
    {
      config = config || {};

      // PRIVATE MEMBER DATA ========================================
      var accountId = Ext.id( null, 'ls-accountDiv-');

      // PUBLIC METHODS ========================================
      this.somePublicMethod = function(){
         console.log( accountId );
      };

...
person Upperstage    schedule 28.04.2010
comment
+1 Работает! Но я только что понял другое решение, которое кажется лучше. Потому что с вашим решением время создания каждого экземпляра будет увеличено, а у меня нет. Я собираюсь опубликовать это сейчас, чтобы люди могли сказать, ошибаюсь я или нет. - person Mariano Desanze; 29.04.2010
comment
Я приветствую этот разговор. Возможно, слишком мало разработчиков беспокоятся о сокрытии данных при разработке на JavaScript. - person Upperstage; 29.04.2010

В следующем примере показан способ Upper Stage. для определения привилегированных частных и общедоступных членов. Но также показано, как определять частные статические члены (также называемые членами класса) и общедоступные непривилегированные члены. . Используя эти последние 2 вместо привилегированных, мы сократим время инициализации, поскольку они не анализируются каждый раз, когда вы создаете новый объект вашего класса:

Ext.ux.MyExtendedClass = Ext.extend(Ext.util.Observable, 
  (function() {
    // private static fields (can access only to scope: minimum privileges).
    var privStaticVar = 0;
    // private static functions (can access only to scope and arguments, but we can send them the scope by param)
    var privateFunc1 = function(me) { return me.name + ' -> ClassVar:' + privStaticVar; };
    var privateFunc2 = function(me) { return me.publicMethod1() + ' InstanceVar:' + me.getPrivateVar(); };
    return {
      constructor: function(config) {
        // privileged private/public members (can access to anything private and public)
        var privateVar = config.v || 0;
        var privInstFunc = function() { privateVar += 1; };
        this.name = config.name;
        this.incVariables = function(){ privInstFunc(); privStaticVar += 1; };
        this.getPrivateVar = function(){ return privateVar; };
      },
      // public members (can access to public and private static, but not to the members defined in the constructor)
      publicMethod1: function() { this.incVariables(); return privateFunc1(this); },
      publicMethod2: function() { return privateFunc2(this); }
    };
  }())
);

function test() {
  var o1 = new Ext.ux.MyExtendedClass({name: 'o1', v: 0});
  var o2 = new Ext.ux.MyExtendedClass({name: 'o2', v: 10});
  var s = o1.publicMethod2() + '<br>' + o1.publicMethod2() + '<br><br>' + o2.publicMethod2() + '<br>' + o2.publicMethod2();
  Ext.get("output").update(s);
}
<link href="//cdnjs.cloudflare.com/ajax/libs/extjs/3.4.1-1/resources/css/ext-all.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/extjs/3.4.1-1/adapter/ext/ext-base.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/extjs/3.4.1-1/ext-all.js"></script>

<p>Click the button to instantiate 2 objects and call each object 2 times:</p>

<button onclick="test();">Test</button>

<p>You can click the button again to repeat. You'll see that the static variable keep increasing its value.</p>

<p>&nbsp;</p>
<div id="output"></div>

person Mariano Desanze    schedule 29.04.2010
comment
это обычно называется шаблоном модуля, вы можете найти его в блоге YUI. - person seanmonstar; 29.04.2010
comment
Я уверен, что privStaticVar, privateFunc1 и privateFunc2 будут проанализированы только один раз (и с помощью проведенных тестов я получил правильные результаты) . Поскольку ключевое слово new не повлияет на члены этого шаблона модуля, поскольку они анализируются во время выполнения Ext.extend (задолго до того, как конструктор или любой другой метод появится на сцене). Кроме того, шаблоны модулей являются синглтонами, поэтому я думаю, что это тоже объясняет это. - person Mariano Desanze; 29.04.2010
comment
Я согласен; извините за предыдущий комментарий. - person Upperstage; 29.04.2010
comment
@Proton шаблон модуля не должен создавать синглтоны. его больше для описания действия по заключению объявлений переменных в самовыполняющуюся функцию и возврату и объекту, который имеет доступ к этим переменным. - person seanmonstar; 29.04.2010
comment
@seanmonstar yuiblog/module-pattern говорит: Douglas Crockford has been teaching a useful singleton pattern for achieving this discipline, and I thought his pattern might be of interest to those of you building on top of YUI. Douglas calls this the “module pattern.” Но ты прав! Потому что я использую его в этом классе, а класс в целом не является синглтоном. Хотя он разделяет статичность синглтона. - person Mariano Desanze; 30.04.2010

@Protron: Ваш ответ потрясающий! Спасибо! Я пошел немного дальше и создал свой собственный метод расширения класса.

/**
 * Instead of call Ext.extend method to create your new class extensions, you can use
 * My.extend. It is almost the same thing, but you pass a function as body for your new class, not
 * an object. Ex.:
 *
 * MyNewExtCompoment = My.extend(Ext.Compoment, function() {
 *     var myPrivateVar = 0;
 *
 *     //private
 *     function reset() {
 *       myPrivateVar = 0;
 *     }
 *
 *     //public
 *     function add(value) {
 *       try{
 *         myPrivateVar = myPrivateVar + value;
 *       } catch(err){
 *         reset();
 *       }
 *       return myPrivateVar;
 *     }
 *
 *     return {
 *         add: add
 *     }
 * }, 'ux-my-new-component');
 *
 * @param extendedClass my extended class
 * @param newClassBodyFunction my new class body
 * @param newClassXtype (optional) the xtype of this new class
 */
My.extend = function(extendedClass, newClassBodyFunction, newClassXtype) {
    var newClass = Ext.extend(extendedClass, newClassBodyFunction.call());
    if(newClassXtype) {
        Ext.reg(newClassXtype, newClass);
    }
    return newClass;
}

Таким образом, мы можем сэкономить несколько дополнительных "()", и у нас есть "Ext.reg", вызываемый бесплатно. [] с

person Thiago Veronezi    schedule 02.09.2011