SAPUI5 JSONModel extended as singleton instance - singleton

I'd like to know if is possible to create a JSONModel extended and make it as singleton instance.
I've already created my extended JSONModel but I need to use it in different parts of my app.
How to turn the constructor of my model private and create the getInstance method?
Thanks for help!

If you want to be able to access your model from anywhere, you don't necessarily need to create a singleton. You could for example create the model instance and assign them to the UI5 Core.
// Where you create your model
var oModel = new CustomModel();
sap.ui.getCore().setModel(oModel);
// To access the model from anywhere
var oModel = sap.ui.getCore().getModel();
If you insist on having a singleton, you could simply remove the constructor once the instance has been created:
(function() {
"use strict";
var oInstance;
sap.ui.model.json.JSONModel.extend("CustomModel", {
constructor : function() {
sap.ui.model.json.JSONModel.apply(this, arguments);
if (oInstance) {
throw "Constructor of singleton cannot be called"
}
}
});
CustomModel.getInstance = function() {
if (!oInstance) {
oInstance = new CustomModel();
oInstance.constructor = null
}
return oInstance;
};
}());
That's just from the top of my head so there might by typos in there.
On a side note, I would highly recommend reading What is so bad about singletons? and instead of using them, rather inject the model to your dependencies.

Related

I can't create a new instance of a ClassMirror by calling the defaullt constructor

I have two classes
class ESVAPI extends BibleProvider {
ESVAPI() : super('esvapi', true, {'esv'});
...methods
}
abstract class BibleProvider {
...fields
BibleProvider(this.name, this._requiresKey, this._versions) {
Bible.addProvider(this, _versions.toList());
}
}
I intend to have multiple classes extend the abstract class, so I want to create a method that creates an instances of each of BibleProvider's subclasses, I created one here:
ClassMirror classMirror = reflectClass(BibleProvider);
List<DeclarationMirror> subClassMirrors = currentMirrorSystem()
.libraries
.values
.expand((lib) => lib.declarations.values)
.where((lib) {
return lib is ClassMirror &&
lib.isSubclassOf(classMirror) &&
lib != classMirror;
}).toList();
DeclarationMirror subClassDec = subClassMirrors[0];
ClassMirror ESVCLASS = reflectClass(subClassDec.runtimeType);
var esvObj = ESVCLASS.newInstance(const Symbol(''), []);
But on ESVCLASS.newInstance I receive this exception:
No constructor '_ClassMirror' declared in class '_ClassMirror'
I'm thinking that this may have to do with how I call the superclass in the Constructor with "hard coded" values. If this is the case, is there a way to call the subclass' constructor and have it call the super constructor? I'm not entirely sure. Anyone familiar with reflections know what may be the case?
Change the last three lines to:
ClassMirror subClassDec = subClassMirrors[0] as ClassMirror;
var esvObj = subClassDec.newInstance(const Symbol(''), []);
...
print(esvObj.reflectee.runtimeType); // ESVAPI
You are reflecting on something that is already a mirror, so your ESVCLASS becomes the class mirror of the class _ClassMirror itself, not the subclass of BibleProvider you found above.
Just use the subClassDec class mirror directly.

Provide an Instance as its interface in Koin

Lets say I have two interfaces like:
interface LetterClassifier
interface NumberClassifier
Then these interfaces would be applied to this class:
class Classifier() : LetterClassifier, NumberClassifier
Now, I want to provide these instances only as LetterClassifier and NumberClassifier and not as Classifier in Koin.
The way I think of doing this is by doing:
module {
val classifier = Classifier()
single<NumberClassifier> { classifier }
single<LetterClassifier> { classifier }
}
But I don't think this is the right way. Can someone guide me?
You could bind types to your definition like it is described on official article:
single { Classifier() } binds arrayOf(LetterClassifier::class, NumberClassifier::class)
If you want to exclude Classifier type at all you could do something like:
single<LetterClassifier> { Classifier() } bind NumberClassifier::class
The way you're doing it is in fact the right way! Here's another example from the Koin docs, doing the same thing:
class DataRepository()
interface Presenter
class MyPresenter(val repository : Repository) : Presenter
val myModule = module {
// Define a singleton for type DataRepository
single { DataRepository() }
// Define a factory (create a new instance each time) for type Presenter (infered parameter in <>)
// Resolve constructor dependency with get()
factory<Presenter> { MyPresenter(get()) }
}
One small thing to note when doing this: your approach immediately creates an instance at the time the module declaration is being processed, while placing the constructor calls in the single lambdas would create instances when needed:
single<NumberClassifier> { Classifier() }
single<LetterClassifier> { Classifier() }
Although this would create a separate single instance for both of the interfaces.
You can have a function or a Singleton to provide instance,
single<NumberClassifier> { Singleton.createClassifier() }
single<LetterClassifier> { Singleton.createClassifier() }

how uses "uses" attribute in Ext.define?

How use "uses" attribute in Ext.define ?
Please example
I could find on the topic only Sencha Ext.define Uses vs Requires
Ext.define('Mother', {
uses: ['Child'],
giveBirth: function() {
// This code might, or might not work:
// return new Child();
// Instead use Ext.create() to load the class at the spot if not loaded already:
return Ext.create('Child');
}
});
List of optional classes to load together with this class. These aren't neccessarily loaded before this class is created, but are guaranteed to be available before Ext.onReady listeners are invoked.

lua / luabind - Add and overwrite class methods through lua

I'm using lua 5.2.2 with luabind 0.9.
I'd like to be able to add additional class-methods through lua for any classes that I've bound in c++, but I'm unsure how to do it.
The problem is that luabind uses a function as the __index-metamethod for any bound classes instead of a table, so I don't see a way to access the class-methods at all.
e.g., I'm binding my classes like this:
luabind::module(lua)
[
luabind::class_<testClass>("TestClass")
.def(luabind::constructor<>())
.def("TestFunc",&TestFunc)
];
What I essentially want to do is to add a lua-function to the list of methods for this class, and be able to overwrite existing ones:
local t = tableOfClassMethods
local r = t.TestFunc -- Reference to the c++-function we've bound
t.SomeFunction = function(o) end -- New function for all objects of this class
t.TestFunc = function(o) end -- Should overwrite the c++-function of the same name
Any help would be appreciated.
You could use a luabind::object property and register it with the .property method of luabind
Something like this:
//Class
class FunctionCaller
{
public:
luabind::object Fn;
void SetFn(luabind::object NewFn)
{
Fn = NewFn;
};
luabind::object GetFn()
{
return Fn;
};
};
//Binding Code
luabind::class_<FunctionCaller>("FunctionCaller")
.def(luabind::constructor<>())
.property("Fn", &FunctionCaller::Fn, &FunctionCaller::SetFn, &FunctionCaller::GetFn)
Then you just need to call the luabind::object according to the luabind docs.
It's not exactly what you want to do but it could help you overwrite the function I think. You could bind the real function and have a property, check if the luabind::object is non-null, and call it or the native function.

Ext.Create returning classes that are already instantiated

I'm making use of the extjs class objects through Ext.define (... and Ext.create (.... When I have multiple instances of classes stored within another class I'm seeing some strange behavior: the classes are not unique and it looks like Ext.create is returning my previous instantiation.
Checkout the JSFiddle of my problem here. Make sure you view the console log in your browser to see the output and weirdness.
You're setting an array in Ext.define. That implies that you're setting into the object's prototype which is shared among all instances of a class. Therefore this is not an unexpected behaviour. Create the array within the constructor, like here:
Ext.define ('Sunglasses', {
brand : '',
constructor : function (args) {
this.lenses = [];
this.brand = args.brand;
},
addLenses : function (lenses) {
this.lenses.push (lenses);
}
});