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

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.

Related

Koin - How to generify Singleton creation?

I have a class InteractorCache<T> that I would like to inject in different places using Koin.
I would like to create a singleton instance of that class based on the type T. So if I have 10 types T, I would like 10 different singletons.
So far I managed to do the above with the following code (this is an example with only 2 types, A and B):
val interactorAModule = module {
factory {
InteractorA(get())
}
}
val aCache = module {
single(named("A")){
InteractorCache<List<A>>()
}
}
val interactorBModule = module {
factory {
InteractorB(get())
}
}
val bCache = module {
single(named("B")){
InteractorCache<List<B>>()
}
}
This works but there is a lot of repetition as I have to create a new cache module (aCache, bCache) every time I create a new type. I would like to be able to do something like this instead:
val cacheModule = module{
single<T>{
InteractorCache<T>()
}
}
so there is only 1 declaration that works for any type T.
Is there a way to do this in Koin?
Although this is late but the idea of making generic or T a singleton is bad idea, when you declare a class singleton it will run a single instance, so runtime error would be InteractorCache() is incompatible or mismatched to InteractorCache() as the first class you would assign the T for example the class A InteractorCache() it would be fixed instance of A and cannot anymore assign to class B.

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

What is the use of open properties in Kotlin?

I have been learning Kotlin and have come across the concept of open properties. Coming from C++, the concept of "open" makes sense, and extending that logic to properties does as well. However, I can't think of any case where an open val/var is actually necessary or useful. I understand when they make sense for interfaces, but not concrete classes. Furthermore, overriding getters/setters makes sense, but not redefining the property with a new backing field. For example, say you have this kind of class structure:
open class Foo {
open var str = "Hello"
}
class Bar : Foo() {
override var str = "world"
init {
println(str)
println(super.str) // Shows that Bar actually contains "hello" and "world"
}
}
To me, it would seem to be a far better design to make Foo take str as a constructor argument, for instance:
open class Foo(var str = "Hello") // Maybe make a secondary constructor
class Bar : Foo("world") // Bar has only 1 string
This is both more concise, and seems to often be a better design. This is also the way it tends to be done in C++, so maybe I just don't see the benefit of the other way. The only possible time I can see overriding a val/var with a new one is if it for some reason needs to use super's value, like in
override val foo = super.foo * 2
Which still seems pretty contrived.
When have you found this useful? Does it allow for greater efficiency or ease of use?
open fields let you re-define getter and setter methods. It's practically pointless if you just return constants. However altering getter / setter behavior has (infinite) potential, so I'll just throw some ideas:
// propagate get/set to parent class
class Bar : Foo() {
override var str
get() = super.str.toUpperCase()
set(value) {
super.str = value
}
}
// creates a backing field for this property
class Bar : Foo() {
override var str = "World"
get() = field.toLowerCase()
// no need to define custom set if we don't need it in this case
// set(value) { field = value }
}
// instead of writing custom get/set, you can also use delegates
class Bar : Foo() {
override var str by Delegates.observable("world"){ prop, old, new ->
println("${prop.name} changed from $old to $new")
}
}

Describing a function parameter that takes a class as an argument in TypeScript

I want to write a function where you parse the class type (the class, not an instance) then the function will instantiate an instance based on that parameter.
This is best explained by example:
//All possible paramter types must inherit from this base class
class Base { public name : string = ''; }
//These are possible classes that could be parsed to the function
class Foo extends Base { constructor() { super(); console.log("Foo instance created"); } }
class Bar extends Base { constructor() { super(); console.log("Bar instance created"); } }
//This function should take a class that inherits from 'Base' as a paramter - then it will create an instance
function Example(param : ?????????) : Base //I don't know what type the 'param' should be
{
return new param(); //Create instance?? How do I do this
}
//This should be the output - if it worked (but it doesn't)
Example(Foo); //Logs "Foo instance created""
Example(Bar); //Logs "Foo instance created""
//So if this worked, it would become possible to do this:
let b : Foo = Example(Foo);
let c : Bar = Example(Bar);
So my questions is: what type would the param for the 'Example' function be? And how would I create an instance of param from within the function.
Note, if this question is a duplicate I apologise - but I don't know the technical name for this process so it is difficult to research.
You want something like this.
function Example<T extends Base>(param: new () => T): T {
return new param();
}
We know that you'll have some type that is a Base. We're going to name it T, and we'll say that T extends Base to enforce that.
We also know that param will construct a T with no parameters. We can write new () => T to describe that.
Basically the way to think about this is that a class has both an instance side and a static side (also called the "constructor" side). In your example, Base, Foo, and Bar on their own have the static side.
The static side for each of them consists of all the static members you specify (and there aren't any in this case), along with the construct signature. In your case, Example takes a constructor expects no arguments, and produces some subtype of Base.

SAPUI5 JSONModel extended as singleton instance

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.