Lepszy sposób wywołania metody superclass w ExtJS
Cała dokumentacja i przykłady ExtJS, które przeczytałem, sugerują wywołanie metod klasy superclass w następujący sposób:
MyApp.MyPanel = Ext.extend(Ext.Panel, {
initComponent: function() {
// do something MyPanel specific here...
MyApp.MyPanel.superclass.initComponent.call(this);
}
});
Używam tego wzorca od dłuższego czasu i głównym problemem jest to, że kiedy zmienisz nazwę swojej klasy, musisz również zmienić wszystkie wywołania na metody superclass. To dość niewygodne, często zapominam, a potem muszę wytropić dziwne błędy.
Ale czytając Źródło Ext.extend()
odkryłem, że zamiast tego mogę użyć superclass()
lub super()
metody, któreExt.extend()
dodają do prototypu:
MyApp.MyPanel = Ext.extend(Ext.Panel, {
initComponent: function() {
// do something MyPanel specific here...
this.superclass().initComponent.call(this);
}
});
W tym kodzie zmiana nazwy MyPanel na coś innego jest prosta - muszę tylko zmienić jedną linię.
Ale mam wątpliwości...Nigdzie nie widziałem tego udokumentowanego, a stara mądrość mówi, że nie powinienem polegać na nieudokumentowanym zachowaniu.
Nie znalazłem ani jednego zastosowania tych metod
superclass()
isupr()
w kodzie źródłowym ExtJS. Po co je tworzyć, skoro nie masz zamiaru używać oni?Może te metody były używane w niektórych starszych wersjach ExtJS, ale są teraz przestarzałe? Ale wydaje się to tak przydatna funkcja, dlaczego miałbyś ją dezaktualizować?
Więc, powinienem używać tych metod, czy nie?
6 answers
Tak rzeczywiście, supr()
nie jest udokumentowane. Nie mogę się doczekać, aby użyć go w ExtJS 3.0.0( członek personelu Ext odpowiedział na forum, dodali go w tej wersji), ale wydaje się strasznie zepsuty.
Obecnie nie przechodzi przez hierarchię dziedziczenia, ale raczej idzie o jeden poziom, a następnie utknie na tym poziomie, pętli bez końca i wysadza stos (IIRC). Tak więc, jeśli masz dwa lub więcej supr()
z rzędu, Twoja aplikacja pęknie. Nie znalazłem żadnych przydatnych informacji na supr()
w ani dokumentów, ani forów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-12 21:05:00
Myślę, że jest to rozwiązane w ExtJS 4 z 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]);
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-04 08:22:49
Oto wzór, którego używam i mam zamiar blogować o nim od jakiegoś czasu.
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);
Istnieje wiele funkcji, które można uzyskać za pomocą tego wzoru, ale nie musisz używać wszystkich z nich
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-14 21:13:32
Możesz użyć tej mało znanej funkcji Javascript (argumenty.callee):
MyApp.MyPanel = Ext.extend(Ext.Panel, {
constructor: function() {
// Do your thing
this.thing = 1;
// Call super
arguments.callee.superclass.constructor.apply(this, arguments);
}
});
Patrz dokumentacja MDC
Edit: właściwie, to nie będzie działać z initComponent, ponieważ to nie jest konstruktor. Ja osobiście zawsze nadpisuję konstruktor (pomimo tego co sugerują przykłady Ext JS). Będę się nad tym trochę zastanawiał.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-12 21:02:38
Po prostu zmieniłbym Twój kod na:
var $cls = MyApp.MyPanel = Ext.extend(Ext.Panel, {
initComponent: function() {
// do something MyPanel specific here...
$cls.superclass.initComponent.call(this);
}
});
W ten sposób zachowasz tylko jedno odniesienie do nazwy twojej klasy, teraz $cls. Używaj tylko $cls w swoich metodach klasowych, a wszystko będzie dobrze.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-10 10:13:41
Wymyśliłem to rozwiązanie kilka godzin temu heheh...
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;
}
Wtedy możesz zrobić:
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);
}
});
Testowane tylko z (Chromium 8.0.552.237 (70801) Ubuntu 10.10) oraz (Firefox 3.6.13).
Mam nadzieję, że to komuś pomoże, prawie przerzuciłem się na GWT.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-24 00:32:24