Assume I have a class containing a static function:
class TextUtils {
static Text bold(String text) {
return Text(text, TextStyle(fontWeight: FontWeight.bold,),);
}
}
So when I want to use it:
import 'ui/text.dart'
// ...
TextUtils.bold("Hello");
Is there any way not to bring class name before function? Like it is in Kotlin?
import 'ui/text.dart' // someHow
// ...
bold("Hello");
No, there is no such feature in Dart.
Actually there is the opposite of it. A global function can be used with a prefix, as if it is a static method of some class.
import 'package:lib2/lib2.dart' as lib2;
lib2.Element element2 = lib2.Element();
Related
I want to invoke functions of a class by their names inside a string. I know my best option are Mirrors.
var ref = reflect(new TestClass());
ref.invoke(Symbol("test"), []);
It works fine, I can call the function test by a string. But I also want to put "TestClass" inside a string. Is it possible somehow ?
var ref = reflect("TestClass");
ref.invoke(Symbol("test"), []);
Jonas
You can do something like this:
import 'dart:mirrors';
class MyClass {
static void myMethod() {
print('Hello World');
}
}
void main() {
callStaticMethodOnClass('MyClass', 'myMethod'); // Hello World
}
void callStaticMethodOnClass(String className, String methodName) {
final classSymbol = Symbol(className);
final methodSymbol = Symbol(methodName);
(currentMirrorSystem().isolate.rootLibrary.declarations[classSymbol]
as ClassMirror)
.invoke(methodSymbol, <dynamic>[]);
}
Note, that this implementation does require that myMethod is static since we are never creating any object but only operate directly on the class itself. You can create new objects from the class by calling newInstance on the ClassMirror but you will then need to call the constructor.
But I hope this is enough. If not, please ask and I can try add some more examples.
I am creating some classes and I am getting this issue: Static members from supertypes must be qualified by the name of the defining type.
post(Documnet document) ->Future
My clases are these:
UserApi
import '../api-helper.dart';
import '../../graphql/documents/login.dart';
import 'dart:async';
class UserAPI extends APIHelper {
static Future<dynamic> login(account) async {
return await post(new Login('name', 'email', 'token', 'refreshToken', 'createdAt', 'expiresAt', false));
}
}
APIHelper
import 'package:graphql_flutter/graphql_flutter.dart' show Client, InMemoryCache;
import '../graphql/document.dart';
import '../graphql/graphql-helper.dart';
import 'dart:async';
class APIHelper {
static const GRAPHQL_URL = 'https://heat-map-api.herokuapp.com/graphql';
static final _client = Client(
endPoint: GRAPHQL_URL,
cache: new InMemoryCache(),
);
static Future<dynamic> post(Document document) async {
return await _client.query(query: GraphQLHelper.getBodyMutation(document), variables: GraphQLHelper.getVariables(document));
}
}
What should I do in order to fix this? I don't have compiled the project yet, but it scares me.
Static members can only be used (outside of their class) by prefixing with the class name.
A better design for helper like that is to use top-level members. See AVOID defining a class that contains only static members rule from the Effective Dart
.
using source_gen package how can I call a generator using an extended annotation?
Let's say I have next generator:
class MyAnnotationGenerator extends GeneratorForAnnotation<MyAnnotation> {
const MyAnnotationGenerator();
Future<String> generateForAnnotatedElement(ClassElement element, Serializable annotation, BuildStep buildStep) async {
...
}
I would like to call MyAnnotationGenerator for every annotation that extends MyAnnotation. For example:
class MyAnnotation {
const MyAnnotation();
}
class MyExtendedAnnotation extends MyAnnotation {
const MyExtendedAnnotation();
}
so every time the annotation MyExtendedAnnotation is used I would like to call MyAnnotationGenerator.
I don't believe you can with GeneratorForAnnotation.
You could implement the Generator interface and do the checks yourself though.
GeneratorForAnnotation does not check extended annotation.
You could write your own generator and do the check,
if you don't want to, you will have to set a generator by annotation class.
class MyAnnotationGenerator extends GeneratorForAnnotation<MyAnnotation>
class MyExtendAnnotationGenerator extends GeneratorForAnnotation<MyExtendedAnnotation>
new GeneratorBuilder(const [
const MyAnnotationGenerator(),
const MyExtendAnnotationGenerator()
])
Say I have the following Annotation and 2 classes:
class AppModel extends Reflectable {
final String name;
const AppModel([this.name])
: super(newInstanceCapability, metadataCapability);
}
const appModel = const AppModel();
#appModel
class ImGonnaBePickedUp {
}
#AppModel(' :( ')
class AndImNotPickedUpOnServer_IDoOnWebClient {
}
main() {
appModel.annotatedClasses // that's what I mean by "Picked Up".
}
On CmdApp side (Server): only AndImNotPickedUpOnServer_IDoOnWebClient is given in appModel.annotatedClasses.
On the web side, both classes are given.
Long story short, how do I retrieve classes annotated with direct const constructor calls like in the example above #AppModel(' :( ') (for both CmdApp and Web)?
since version 0.5.4 reflectable classes doesn't support constructors with arguments
This appears in reflectable documentation:
Footnotes: 1. Currently, the only setup which is supported is when the metadata object is an instance of a direct subclass of the class [Reflectable], say MyReflectable, and that subclass defines a const constructor taking zero arguments. This ensures that every subclass of Reflectable used as metadata is a singleton class, which means that the behavior of the instance can be expressed by generating code in the class. Generalizations of this setup may be supported in the future if compelling use cases come up.
one possible solution could be to use a second annotation to handle the name, for example:
import 'package:reflectable/reflectable.dart';
import 'package:drails_commons/drails_commons.dart';
class AppModel extends Reflectable {
const AppModel()
: super(newInstanceCapability, metadataCapability);
}
const appModel = const AppModel();
class TableName {
final String name;
const TableName(this.name);
}
#appModel
class ImGonnaBePickedUp {
}
#appModel
#TableName(' :( ')
class AndImNotPickedUpOnServer_WorksOnWebClient {
}
main() {
print(appModel.annotatedClasses); // that's what I mean by "Picked Up".
print(new GetValueOfAnnotation<TableName>()
.fromDeclaration(appModel.reflectType(AndImNotPickedUpOnServer_WorksOnWebClient)).name);
}
Note: I'm also using drails_common package
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