代码之家  ›  专栏  ›  技术社区  ›  Rene Saarsoo

在extjs中调用超类方法的更好方法

  •  29
  • Rene Saarsoo  · 技术社区  · 15 年前

    我读过的所有extjs文档和示例都建议调用如下超类方法:

    MyApp.MyPanel = Ext.extend(Ext.Panel, {
      initComponent: function() {
        // do something MyPanel specific here...
        MyApp.MyPanel.superclass.initComponent.call(this);
      }
    });
    

    我使用这种模式已经有一段时间了,主要的问题是,当您重命名类时,您还必须更改对超类方法的所有调用。这很不方便,我经常会忘记,然后我必须找出奇怪的错误。

    但阅读的来源 Ext.extend() 我发现,我可以用 superclass() super() 方法 扩展扩展名() 添加到原型:

    MyApp.MyPanel = Ext.extend(Ext.Panel, {
      initComponent: function() {
        // do something MyPanel specific here...
        this.superclass().initComponent.call(this);
      }
    });
    

    在这段代码中,将mypanel重命名为其他东西很简单——我只需要更改一行。

    但我有疑问…

    • 我在任何地方都没有看到这种记录,老智慧说,我不应该依赖于非法行为。

    • 我没有发现这些东西的一个用途 超类() supr() extjs源代码中的方法。为什么不使用它们就创建它们?

    • 也许这些方法是在一些旧版本的extjs中使用的,但是现在被否决了?但这似乎是一个很有用的特性,为什么你要贬低它呢?

    那么,我是否应该使用这些方法呢?

    6 回复  |  直到 11 年前
        1
  •  14
  •   Jabe    15 年前

    是的, supr() 没有记录。我一直期待着在extjs 3.0.0中使用它(ext的一个工作人员在论坛中回复说,他们在那个版本中添加了它),但它似乎被严重破坏了。

    它目前不遍历继承层次结构,而是向上一个层次,然后停留在这个层次上,无限循环并放大堆栈(IIRC)。所以,如果你有两个或更多 SUPR()。 应用程序将连续中断。我没有找到任何有用的信息 () 无论是文件还是论坛。

    我不知道维护版本3.0.x,因为我没有获得支持许可证…

        2
  •  29
  •   tykovec    13 年前

    我认为这在ExtJS4中是通过callParent解决的。

    Ext.define('My.own.A', {
        constructor: function(test) {
            alert(test);
        }
    });
    
    Ext.define('My.own.B', {
        extend: 'My.own.A',
    
        constructor: function(test) {
            alert(test);
    
            this.callParent([test + 1]);
        }
    });
    
        3
  •  5
  •   Ruan Mendes    12 年前

    这是我使用的一个模式,我想在博客上写一段时间。

    Ext.ns('MyApp.MyPanel');
    
    MyApp.MyPanel = (function(){
      var $this = Ext.extend(Ext.Panel, {
        constructor: function() {
            // Using a 'public static' value from $this
            // (a reference to the constructor)
            // and calling a 'private static' method
            this.thing = $this.STATIC_PROP + privateStatic();
            // Call super using $super that is defined after 
            // the call to Ext.extend
            $super.constructor.apply(this, arguments);
        },
        initComponent: function() {
            $super.initComponent.call(this);
            this.addEvents([Events.SOMETHING]); // missing docs here
        }
      });
      var $super = $this.superclass;
    
      // This method can only be accessed from the class 
      // and has no access to 'this'
      function privateStatic() {
        return "Whatever";
      }
    
    
      /** 
        * This is a private non-static member
        * It must be called like getThing.call(this);
        */
      function getThing() {
         return this.thing;
      }
    
      // You can create public static properties like this
      // refer to Events directly from the inside
      // but from the outside somebody could also use it as
      //  MyApp.MyPanel.Events.SOMETHING
      var Events = $this.Events = {
          SOMETHING: 'something'
      }
    
      return $this;
    })();
    
    MyApp.MyPanel.STATIC_STRING = 10;
    
    //Later somewhere
    var panel = new MyApp.Mypanel();
    panel.on(MyApp.Mypanel.Events.SOMETHING, callback);
    

    使用这个模式有很多特性,但不必全部使用

        4
  •  3
  •   neonski    15 年前

    您可以使用这个鲜为人知的javascript特性( arguments.calele参数 ):

    MyApp.MyPanel = Ext.extend(Ext.Panel, {
        constructor: function() {
            // Do your thing
            this.thing = 1;
    
            // Call super
            arguments.callee.superclass.constructor.apply(this, arguments);
        }
    });
    

    看见 MDC documentation

    编辑:实际上,这不适用于initcomponent,因为它不是构造函数。我总是亲自重写构造函数(尽管ExtJS示例建议这样做)。会继续考虑这个问题。

        5
  •  2
  •   Gad    14 年前

    我只需将您的代码更改为:

    var $cls = MyApp.MyPanel = Ext.extend(Ext.Panel, {
      initComponent: function() {
        // do something MyPanel specific here...
        $cls.superclass.initComponent.call(this);
      }
    });
    

    这样,您只保留一个类名的引用,现在是$cls。只在类方法中使用$cls,这样就可以了。

        6
  •  0
  •   rseidi    13 年前

    几个小时前我想出了这个解决方案,呵呵……

    function extend (parentObj, childObj) {
        parentObj = parentObj || function () {};
    
        var newObj = function () {
            if (typeof this.initialize == 'function') {
                this.initialize.apply(this, arguments);
            }
        }
    
        newObj.prototype.__proto__ = parentObj.prototype;
    
        for (var property in childObj) {
            newObj.prototype[property] = childObj[property];
        }
    
        newObj.prototype.superclass = function (method) { 
            var callerMethod = arguments.callee.caller,
                currentProto = this.constructor.prototype.__proto__;
    
            while (callerMethod == currentProto[method]) {
                currentProto = currentProto.__proto__;
            } 
    
            return currentProto[method]; 
        };
    
        return newObj;
    }
    

    然后你可以做:

    var A = function () { 
        this.name = "A Function!";
    };
    
    A.prototype.initialize = function () {
        alert(this.name);
    }
    
    var B = extend(A, {
        initialize: function () {
            this.name = "B Function!";
            this.superclass('initialize').apply(this);
        }
    });
    
    var C = extend(B, {
        initialize: function () {
            this.superclass('initialize').apply(this);
        }
    });
    

    仅用(铬8.0.552.237(70801)Ubuntu 10.10)进行试验 和(火狐3.6.13)。

    希望这能帮上忙,我差点就要换GWT了。