开发者

Private members when extending a class using ExtJS

I have done some research on the ExtJS forum regarding private methods and fields inside a extended class, and I couldn't find any real answer to this.

And when I say an extended class I mean something like this:

Ext.ux.MyExtendedClass = Ext.extend(Ext.util.Observable, {
    publicVar1: 'Variable visible from out开发者_如何学Goside 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
});

The problem here is that everything is public. So, how do I add a new variable o method within the scope of MyExtendedClass that cannot be accessed from outside but can be access by the public methods?


The following example shows the Upper Stage way to define privileged private & public members. But it also shows how to define private static members (also called class members), and public non-privileged members. Using these last 2 instead of the privileged ones, we will reduce initialization time as they are not parsed every time you create a new object of your class:

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>


I use something like the following.

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

...


@Protron: Your answer is awesome! Thanks! I went a little bit further and created my own class extender method.

/**
 * 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;
}

This way we can save some extra "()", and we have the "Ext.reg" called for free. []s

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜