PDA

View Full Version : Improvement: Defining an encapsulated class



apleshkov
20 May 2011, 12:54 PM
Sometimes it's necessary to define a local/encapsulated class and use it only in some local scope.

With Ext 3 I can do this:


(function () {

var MyLocalClass = Ext.extend(ParentClass, {

// ...

});

})();


But in Ext 4 I can't find any way to define such class.
So I've created a little function to do this stuff:


var defineAnonymous = function (data, createdFn) {
data = data || {};

var ret = null;

var postprocessor = function (className, cls, clsData, process) {
ret = cls;
return false;
};

data.postprocessors = data.postprocessors || [];

if (data.singleton !== undefined) {
data.postprocessors.push('singleton');
}

data.postprocessors.push(postprocessor);

Ext.define('AnonymousClass', data, createdFn);

return ret;
};


TESTS

Basic


(function () {

var MyLocalClass = defineAnonymous({

extend: 'Ext.picker.Date',

format: 'Y',

getMyParameter: function () {
return Ext.Date.format(this.getValue(), this.format);
}

}, Ext.emptyFn);

console.info(window.AnonymousClass); // undefined

console.info(typeof AnonymousClass); // undefined

console.info(new MyLocalClass().getMyParameter()); // 2011

console.info(MyLocalClass.$className); // AnonymousClass

console.info(new MyLocalClass().$className); // AnonymousClass

})();


Singleton


(function () {

var MyLocalSingleton = defineAnonymous({

singleton: true,

getSomeParam: function () {
return 1;
}

});

try {
console.error(new MyLocalSingleton().getSomeParam());
} catch (e) {
console.info('OK'); // OK
}

console.info(MyLocalSingleton.getSomeParam()); // 1

console.info(MyLocalSingleton.$className); // AnonymousClass

})();


Is it possible to add such function to Ext 4?

dongryphon
20 May 2011, 10:30 PM
Perhaps something of this form?



(function () {

var MyClass = Ext.define(null, {
});

});


Just like normal but no public name. Thoughts?

LesJ
21 May 2011, 2:09 AM
Neat, but this syntax won't work with singletons:


(function () {

var MyClass = Ext.define(null, {
singleton: true
});

});

apleshkov
21 May 2011, 2:36 AM
(function () {

var MyClass = Ext.define(null, {

// anything

});

})();


This code doesn't work because of ClassManager.js:440:

Invalid class name 'null' specified, must be a non-empty string

LesJ
21 May 2011, 3:46 AM
I know that the class name is required, but even if anonymous classes were supported, this syntax wouldn't work for singletons b/c the name is required for singletons.

apleshkov
21 May 2011, 4:59 AM
I know that the class name is required, but even if anonymous classes were supported, this syntax wouldn't work for singletons b/c the name is required for singletons.

It doesn't matter if you want to define a basic class or a singleton, because Ext.define(null, ...) simply doesn't work at all.

I've added singleton support to my function. Check it out.

LesJ
21 May 2011, 7:16 AM
I just wanted to point out that the syntax that dongryphon provided won't work. It would be nice if it worked though :)

This is exactly how anonymous classes are created in Dojo.

http://dojotoolkit.org/documentation/tutorials/1.6/declare/

Now to provide support for anonymous classes in Ext, you would have to create a new function (syntax), which is clumsy.

apleshkov
21 May 2011, 7:45 AM
I just wanted to point out that the syntax that dongryphon provided won't work. It would be nice if it worked though :)

OMG... Shame on me! I didn't notice dongryphon's code is just an offer, but not a real solution I could use right now with my current version of Ext 4. Please, sorry about that. I should take a vacation as soon as possible :)


This is exactly how anonymous classes are created in Dojo.

http://dojotoolkit.org/documentation/tutorials/1.6/declare/


Very similar to dongryphon's idea.


Now to provide support for anonymous classes in Ext, you would have to create a new function (syntax), which is clumsy.

Fully agree with you, it's clumsy.


Neat, but this syntax won't work with singletons

dongryphon? :)

dongryphon
21 May 2011, 8:08 PM
Sorry for the confusion - I was suggesting a syntax not currently supported to see what folks thought of it.

Is singleton that much of an issue in a small, private scope? It is more of an issue for shared stuff.

If the hypothetical syntax worked, you could have a "singleton" like so:



(function () {

var MySingleton = new (Ext.define(null, {

// anything

}))();

})();

dongryphon
21 May 2011, 8:11 PM
The null argument is also probably not needed. One argument should work:



(function () {

var MyClass = Ext.define({

// anything

});

var MySingleton = new (Ext.define({

// anything

}))();

})();

apleshkov
22 May 2011, 5:40 AM
Sorry for the confusion - I was suggesting a syntax not currently supported to see what folks thought of it.

Huh, it's only my fault. I should read your and LesJ's posts much more carefully. Sorry again.


Is singleton that much of an issue in a small, private scope? It is more of an issue for shared stuff.

Agree.


The null argument is also probably not needed.

Cool!

Jacky Nguyen
22 May 2011, 2:37 PM
For anonymous class creation, do this:



(function(){

var MyClass = new Ext.Class({
...
})

})();


A few important notes when doing this: no post-processor property can be used in the above method since they belong to the higher level abstraction provided in Ext.ClassManager (Ext.define)

- alias
- singleton
- alternateClassName

Also, dependencies for the anonymous class must then be specified in this format:



Ext.require(['Foo', 'Bar'], function(){

var MyClass = new Ext.Class({
...
});

// MyClass is ready to be used at this point

});


instead of:



(function(){

var MyClass = new Ext.Class({
requires: ['Foo', 'Bar']
...
});

// MyClass is not guaranteed to be ready here since the operation is asynchronous if either 'Foo' or 'Bar' doesn't yet exist
})();

apleshkov
23 May 2011, 9:12 AM
For anonymous class creation, do this...

Works perfectly, thank you!

The one thing I don't like is defining a class by the "new" operator: it looks a bit abnormal as compared with classic OOP languages. For example, Ext.Class.define would be more familiar:


Ext.Class.define = function (classData) {
return new Ext.Class(classData);
};

...

(function () {

var MyClass = Ext.Class.define({

// anything

});

})();