Вопрос

Вся документация ExtJS и примеры, которые я прочитал, предполагают вызов методов суперкласса, подобных этому:

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

Я использую этот шаблон уже довольно давно, и основная проблема заключается в том, что когда вы переименовываете свой класс, вам также приходится изменять все вызовы методов суперкласса.Это довольно неудобно, часто я забываю, и тогда мне приходится выслеживать странные ошибки.

Но, читая источник Ext.extend() Я обнаружил, что вместо этого я мог бы использовать superclass() или super() методы, которые Ext.extend() добавляет к прототипу:

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

В этом коде переименовать MyPanel во что-то другое просто - мне просто нужно изменить одну строку.

Но у меня есть сомнения...

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

  • Я не нашел им ни единого применения superclass() и supr() методы в исходном коде ExtJS.Зачем создавать их, если вы не собираетесь их использовать?

  • Может быть, эти методы использовались в какой-то более старой версии ExtJS, но сейчас устарели?Но это кажется такой полезной функцией, почему вы отказываетесь от нее?

Итак, должен ли я использовать эти методы или нет?

Это было полезно?

Решение

Да , действительно, supr() не задокументировано.Я с нетерпением ждал возможности использовать его в ExtJS 3.0.0 (сотрудник Ext ответил на форумах, что они добавили его в эту версию), но он кажется ужасно сломанным.

В настоящее время он не пересекает иерархию наследования, а скорее поднимается на один уровень выше, затем застревает на этом уровне, бесконечно зацикливается и взрывает стек (IIRC).Итак, если у вас есть два или более supr() через несколько секунд ваше приложение выйдет из строя.Я не нашел никакой полезной информации по supr() ни в документах, ни на форумах.

Я не знаю о версиях обслуживания 3.0.x, поскольку я не получал лицензию службы поддержки...

Другие советы

Я думаю, что это решается в ExtJS 4 с помощью 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]);
    }
});

Вот шаблон, который я использую, и уже некоторое время собирался написать о нем в блоге.

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

Есть много функций, которые вы получаете, используя этот шаблон, но вам не обязательно использовать их все

Вы могли бы использовать эту малоизвестную функцию Javascript (аргументы.вызываемый абонент):

MyApp.MyPanel = Ext.extend(Ext.Panel, {
    constructor: function() {
        // Do your thing
        this.thing = 1;

        // Call super
        arguments.callee.superclass.constructor.apply(this, arguments);
    }
});

видишь Документация MDC

Редактировать:На самом деле, это не будет работать с initComponent, потому что это не конструктор.Лично я всегда переопределяю конструктор (несмотря на то, что предлагают Ext JS examples).Продолжу немного думать об этом.

Я бы просто изменил ваш код на:

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

Таким образом, вы сохраняете только одну ссылку на имя вашего класса, теперь $cls.Используйте только $cls в методах вашего класса, и все будет в порядке.

Я придумал это решение пару часов назад, хе-хе...

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

Тестировался только с (Chromium 8.0.552.237 (70801) Ubuntu 10.10) и (Firefox 3.6.13).

Надеюсь, это кому-нибудь поможет, я уже почти переключился на GWT.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top