Dart ClassMirror newInstance method says no such constructor - dart

I tried to dynamically create a new instance of a class like this:
this.componentClass.newInstance(new Symbol(''), [this, el]).reflectee;
The class reflected in this.componentClass is called ButtonComponent and it is a subclass of Component. When running a test on this, I get an error:
Test failed: Caught No constructor 'ButtonComponent.' declared in class 'ButtonComponent'.
NoSuchMethodError : method not found: 'ButtonComponent.'
Receiver: Type: class 'ButtonComponent' Arguments: [...]
There are default constructors in both Component and ButtonComponent classes. Here is the code, to make sure I didn't miss anything:
class Component {
Element element ;
Template template;
Component(this.template, this.element) {
this.element.replaceWith(new Element.html(template.html));
}
}
class ButtonComponent extends Component {
ButtonComponent(template, element) : super(template, element) {};
}
Any ideas what is wrong here? Thank you.

I just made a similar test in 1.0.0.3_r30187 and I don't get this error. If you don't use the last stable version of Dart you should update your version.
Here's my tested code :
import 'dart:html';
import 'dart:mirrors';
class Component {
Element element ;
Component(this.element) {
this.element.children.add(new Element.html("<b>Dart rocks</b>"));
}
}
class ButtonComponent extends Component {
ButtonComponent(element) : super(element);
}
main() {
final a = reflectClass(ButtonComponent).newInstance(new Symbol(''),
[document.documentElement]).reflectee;
print(a); // display : Instance of 'ButtonComponent'
}

Related

Getting type of another generic type from Dart type parameter

I would like to make a generic class which only accepts Lists as a type parameter. But I also want the type parameter of the List. Something like this:
class MyClass<L extends List<T>> {
T foo() {
// ....
}
}
The problem is that that does not work. T is not found. But this does:
class MyClass<L extends List<T>, T> {
T foo() {
// ....
}
}
My only issue with this is that I have to always pass in the extra parameter T which should be inferred from the List type.
var instance = MyClass<List<int>>();
var instance = MyClass<List<int>, int>(); // Extra int kind of redundant
Is there any workaround to this?
The solution is similar to the one provided in this question (the same problem, but in Java): basically, you can't do that in Dart. What you can do is
create a new subclass:
class MyClass2<T> extends MyClass<List<T>, T> { ... }
or
create a factory method:
class MyClass<L extends List<T>, T> {
static MyClass<List<T>, T> fromList<T>(List<T> list) {
return MyClass(...);
}
}

Is it possible to have a private constructor in dart?

I'm able to do something like the following in TypeScript
class Foo {
private constructor () {}
}
so this constructor is accessible only from inside the class itself.
How to achieve the same functionality in Dart?
Just create a named constructor that starts with _
class Foo {
Foo._() {}
}
then the constructor Foo._() will be accessible only from its class (and library).
A method without any code must be something like this
class Foo {
Foo._();
}
Yes, It is possible, wanna add more information around it.
A constructor can be made private by using (_) underscore operator which means private in dart.
So a class can be declared as
class Foo {
Foo._() {}
}
so now, The class Foo doesn't have a default constructor
Foo foo = Foo(); // It will give compile time error
The same theory applied while extending class also, It's also impossible to call the private constructor if it declares in a separate file.
class FooBar extends Foo {
FooBar() : super._(); // This will give compile time error.
}
But both above functionality works if we use them in the same class or file respectively.
Foo foo = Foo._(); // It will work as calling from the same class
and
class FooBar extends Foo {
FooBar() : super._(); // This will work as both Foo and FooBar are declared in same file.
}
you can create following class in order to get a singleton instance
class Sample{
factory Sample() => _this ??= Sample._();
Sample._(); // you can add your custom code here
static Sample _this;
}
Now in the main function you can call the sample constructor
void main(){
/// this will return the _this instace from sample class
Sample sample = Sample();
}
just use abstract class.
Because you can't instantiate abstract class

How are arguments passed into the parameter list of ClassMirror.newInstance(...)? [duplicate]

I'm perfectly willing to play with this until I get it right, but was hoping someone might give me a hint. The parameter is declared in the docs (gen-dartdocs/dart-mirrors/ClassMirror/newInstance.html) as
InstanceMirror newInstance(Symbol constructorName,
List positionalArguments,
[Map<Symbol,dynamic> namedArguments]);
There is a nice writeup on the format of positionalArguments and namedArguments in the docs. However, it is just a little on the abstract side of my current tolerance level.
A decent discussion also exists at
http://japhr.blogspot.com/2014/06/dart-factory-method-pattern.html
But, alas, no examples of actually passing args into the method.
In my case, I would like to simply pass two args, "title" and "description" into an unnamed subclass constructor.
Here's my code so far:
file: item.dart
import 'dart:mirrors';
abstract class Item {
String title;
String description;
factory Item(String type) {
MirrorSystem libs = currentMirrorSystem();
LibraryMirror lib = libs.findLibrary(new Symbol('app.models'));
Map<Symbol, Mirror> classes = lib.declarations;
// To do: handle exception if class not found
ClassMirror cls = classes[new Symbol(type)];
// TODO:
// verify each subclass has no-arg ctor
// determ how to pass args to ctor.
InstanceMirror inst = cls.newInstance(new Symbol(''), []);
return inst.reflectee;
}
// conflicts w/ Item factory
// Item(this.title, this.description);
}
And here's the class that gets instantiated:
file: model.dart
library app.models;
import 'item.dart' show Item;
/// The barebones model for a codelab. Defines constants used for validation.
class Codelab implements Item {
// ...
}
Finally, here is how the Item factory is called. ItemElement is the superclass of its own hierarchy, subclassed by CodelabElement:
file: item_element.dart:
import 'item.dart' show Item;
class ItemElement {
Item item;
final String itemType;
ItemElement() {
item = new Item(itemType);
}
// ...
}
And CodelabElement:
file: codelab_element.dart
import 'model.dart' show Codelab;
import 'item_element.dart' show ItemElement;
class CodelabElement extends ItemElement {
final itemType = "Codelab";
CodelabElement() : super() {}
//...
}
And then:
file: main.dart
void main() {
var element = new CodelabElement();
}
Currently, the new Codelab instance is returned from newInstance() (very cool), but it doesn't contain the inherited 'title' and 'description' attrs.
Maybe it has something to do with my being unclear on the usage of "extends" and "implements".
This should work
cls.newInstance(new Symbol(''), ['a', 1] /*,
{#arg1Name: 'arg1Value', #arg2Name: 'arg2Value'}*/ );
and is like
new MyClass('a', 1, arg1Name: 'arg1Value' /*, arg2Name: 'arg2Value'*/);
Just saw, Named arguments are not implemented.
You can try it in DartPad

Aurelia & Typescript injection and inheritance

I am working with Aurelia and Typescript and I'm trying to achieve the following thing: have a base class called Parent, extend this class in a class called Child and then inject an instance of Child in another class.
Here's the setup:
//file1
export class Parent {
constructor() {
debugger;
}
}
//file2
import {Parent} from "file1";
export class Child extends Parent {
constructor() {
super();
debugger;
}
}
//file3
import {inject} from "aurelia-framework";
import {Child} from "file2";
#inject(Child)
export class Home {
private child: Child;
constructor(_child: Child) {
this.child = _child;
debugger;
}
}
However, when I do this and instantiate Home, I get the following error:
Uncaught SyntaxError: Unexpected token <
along with ERROR [app-router] Router navigation failed, and no previous location could be restored.
Now, the first error, Uncaught SyntaxError: Unexpected token < gives me a reference to file1.js at the first line. (which strangely contains the html code from the index of the application).
Now, if I take the injection out of file3 and make something like this:
//#inject(Child)
export class Home {
private child: Child;
constructor() {
this.child = new Child(); //here I don't inject, I just
//instantiate a new object of type Child - still the same error
debugger;
}
}
I get exactly the same error, so it doesn't seem to be injection related.
So, how can I have a base class called Parent, extend this class in a class called Child and then inject an instance of Child in another class?
Or is something in my approach that is not right?
Thanks!
UPDATE: The simple fact of having a the call for a new Child() breakes everything, it doesn't matterr if it is called at the loading of the page, in the constructor, or if it is in a method on a button. It breakes when loading.
buttonMethod(){
var x = new Child(); //it breakes the same way
}
Now if I move the Child class in the same file as Home and file3 looks like this:
import {inject} from "aurelia-framework";
import {Parent} from "file1";
export class Home {
child: Child;
constructor() {
this.child = new Child();
debugger;
}
}
export class Child extends Parent {
constructor() {
super();
debugger;
}
}
and I instantiate it like this it works. However, when I try to inject it, so:
import {inject} from "aurelia-framework";
import {Parent} from "file1";
#inject(Child)
export class Home {
child: Child;
constructor(_child: Child) {
this.child = _child;
debugger;
}
}
export class Child extends Parent {
constructor() {
super();
debugger;
}
}
I get: inner error: Error: key/value cannot be null or undefined. Are you trying to inject/register something that doesn't exist with DI?
In the end I want to have them in separate files, but it is a start making it work so:)
Thanks!
Ok, so the Typescript compiler finds file1 because it is in the .csproj file so it doesn't need the full path, but at runtime, the Aurelia framework finds the file (after the typescript code is transpiled) something like localhost/file1.js. So you have 2 possibilities: either create a tsd.json in the typings folder (assuming you are using AMD module system) in which to set the absolute paths for your typescript definitions or always write the full path when importing custom typings.

Error Targeting Instance name from document class AS3

I have a document class with this function on it, it targets a symbol with an instance name of scene4_headlights on the stage:
function accUpdate(e:AccelerometerEvent):void{
scene4_headlights.rotation += (e.accelerationX*10);
}
But I keep getting error 1120: Access of undefined property scene4_headlights even though I have a symbol on the stage with the instance name of scene4_headlights..
Help?
Here you go:
package {
import flash.sensors.Accelerometer;
import flash.events.AccelerometerEvent; //importing everything you need is cruicial
import flash.display.MovieClip;
public class CustomClassName extends MovieClip //your custom class can extend the type of class you used to create your scene4_headlights instance (some prefer using Sprite when the timeline is not required)
{
private var accelerometer = new Accelerometer(); //declare a variable data type: Accelerometer
public function CustomClassName() {
// constructor code
accelerometer.addEventListener(AccelerometerEvent.UPDATE, accUpdate); // add an eventlistener to the variable you just created
}
public function accUpdate(e:AccelerometerEvent): void //declare the function handling the eventlistener
{
scene4_headlights.rotation += (e.accelerationX*10);
trace("The function accUpdate is linked properly"); //trace is your friend
}
}
}

Resources