How to set a custom property for conditional import in Dart? - flutter

Dart allows to use the standard library names for conditional import/export, like this:
export 'src/hw_none.dart' // Stub implementation
if (dart.library.io) 'src/hw_io.dart' // dart:io implementation
if (dart.library.html) 'src/hw_html.dart'; // dart:html implementation
Is it possible to define a custom property/condition? For example, pass it when compiling.
I have a project that I would like to split into two variants: Flutter variant and pure Dart variant. The choice of the variant depends at compile time, and the necessary implements of abstract classes defines at compile time.

Custom properties where an experimental feature in Dart 1. With Dart 2 there is no longer any support for user defined custom conditions in compile time.
Here is the discussion referencing your question.
All you can do is, switch between implementations on run time:
abstract class SomeFactory {
String get message;
factory SomeFactory() {
if(Platform.environment['SOME_VAR'] != null)
return new _SomeImplementation();
return new _SomeOtherImplementation();
}
}
class _SomeImplementation implements SomeFactory {
#override
String get message => 'SomeImplementation';
}
class _SomeOtherImplementation implements SomeFactory {
#override
String get message => "OtherImplementation";
}
Check this blog entry for more details.

Related

Method required by interface not met by extension method

For an education app I'm building, I have a module interface that requires a copyWith method:
abstract class Module {
// ...
Module copyWith() => throw 'You should call the instance\'s copyWith.';
}
The problem is that I'm using a codegen package that generates the copyWith method on an extension for the module subclasses:
part 'audio_module.g.dart';
#immutable
#CopyWith()
class AudioModule implements Module {
/* ... */
}
// GENERATED CODE - DO NOT MODIFY BY HAND
part of audio_module;
// **************************************************************************
// CopyWithGenerator
// **************************************************************************
extension AudioModuleCopyWithExtension on AudioModule {
AudioModule copyWith(/* ... */) {
return AudioModule(/* ... */);
}
}
On my AudioModule class I'm thus getting this error because I think it's not counting extension method:
Missing concrete implementation of 'Module.copyWith'.
Try implementing the missing method, or make the class abstract.
Why is this happening if the subclass (in one way or another) does implements the copyWith?
Thank you
Edit
The workaround I ended up using was to instead use the functional_data code gen package which builds a class with the copyWith method on it that you then extend. No extensions.
With the extension method, your class AudioModule does not implement/override the abstracte method in Module. Extension methods work like static methods under the hood, so it does not really add copyWith() to AudioModule.
Just have a look at the Dart docs or google for Dart extension methods and conflict resolution.

Dart Multiple Annotations & source_gen

I'm trying to create a package for Flutter that provides source generation using source_gen. I would like to be able to annotate a class and fields to identify what needs to be generated. (An example of this would be the libraries Dagger2 or ROOM, for java.)
Given an abstract class:
#ServiceCalls("http://www.whocares.com")
abstract class ServiceCalls
#Get
int getCount();
#Post
void postCount(int count);
}
The following concrete implementation would be generated:
class ServiceCallsImp extends ServiceCalls {
Future<int> getCount() {
// details for implementing a get service call
}
Future<void> postCount(int count) {
// details for implementing a post call
}
}
So, the big questions I'm trying to answer are:
1) Is an abstract class the way to go, or is a part the correct approach?
2) How do I setup builders for a 'recursive' annotation processing? (Annotated fields in an annotated class)
NOTE: I don't really care about service calls, its just an example.

Class#newInstance in GWT

I know that GWT doesn't emulate this method, but I need smth that provide its functionality.
I have tried next approach:
private static <T extends Widget> T createWidget(Class<T> widgetClass) {
return GWT.create(widgetClass);
}
But when I try to compile it I get an error:
Only class literals may be used as arguments to GWT.create()
So, how can I write a foresaid method that will emulate Class#newInstance?
GWT.create() always needs the class literal as argument, which means that you has to pass this: GWT.create(MyClass.class) and no other thing.
This is so because the gwt compiler has to decide which class to pick up in compile time, note that in your code the class is passed in runtime.
If you are planing to use GWT.create for a reduced and well known set of classes you can do something like that:
private static <T extends Widget> T createWidget(Class<T> widgetClass) {
if (ClassA.class.equals(widgetClass)) {
return GWT.create(ClassA.class);
} else if (ClassA.class.equals(widgetClass)) {
return GWT.create(ClassB.class);
}
return null;
}

Is it possible to find all classes annotated with #MyAnnotation using a GWT GeneratorContext?

While creating classes using Generators, it's possible to discover all subclasses of a type. You can find this technique for example in the GWT Showcase source (see full code):
JClassType cwType = null;
try {
cwType = context.getTypeOracle().getType(ContentWidget.class.getName());
} catch (NotFoundException e) {
logger.log(TreeLogger.ERROR, "Cannot find ContentWidget class", e);
throw new UnableToCompleteException();
}
JClassType[] types = cwType.getSubtypes();
I would like to do something similar, but instead of extending a class (or implementing an interface)
public class SomeWidget extends ContentWidget { ... }
, could I also do this by annotating Widgets?
#MyAnnotation(...)
public class SomeWidget extends Widget { ... }
And then finding all Widgets that are annotated with #MyAnnotation? I couldn't find a method like JAnnotationType.getAnnotatedTypes(), but maybe I'm just blind?
Note: I was able to make it work with the Google Reflections library, using reflections.getTypesAnnotatedWith(SomeAnnotation.class), but I'd prefer using the GeneratorContext instead, especially because this works a lot better when reloading the app in DevMode.
Yes - easiest way is to iterate through all types, and check them for the annotation. You might have other rules too (is public, is non-abstract) that should also be done at that time.
for (JClassType type : oracle.getTypes()) {
MyAnnotation annotation = type.getAnnotation(MyAnnotation.class);
if (annotation != null && ...) {
// handle this type
}
}
The TypeOracle instance can be obtained from the GeneratorContext using context.getTypeOracle().
Note that this will only give you access to types on the source path. That is, only types currently available based on the modules being inherited and <source> tags in use.

Does Google Dart support mixins?

I've skimmed through the language documentation and it seems that the Google Dart does not support mixins (no method bodies in interfaces, no multiple inheritance, no Ruby-like modules). Am I right about this, or is there another way to have mixin-like functionality in Dart?
I'm happy to report that the answer is now Yes!
A mixin is really just the delta between a subclass and a superclass. You can then "mix in" that delta to another class.
For example, consider this abstract class:
abstract class Persistence {
void save(String filename) {
print('saving the object as ${toJson()}');
}
void load(String filename) {
print('loading from $filename');
}
Object toJson();
}
You can then mix this into other classes, thus avoiding the pollution of the inheritance tree.
abstract class Warrior extends Object with Persistence {
fight(Warrior other) {
// ...
}
}
class Ninja extends Warrior {
Map toJson() {
return {'throwing_stars': true};
}
}
class Zombie extends Warrior {
Map toJson() {
return {'eats_brains': true};
}
}
Restrictions on mixin definitions include:
Must not declare a constructor
Superclass is Object
Contains no calls to super
Some additional reading:
http://www.dartlang.org/articles/mixins/
http://blog.sethladd.com/2013/03/first-look-at-dart-mixins.html
Edit:
The Dart team have now released their proposal for Mixins, the original issue for Mixins was here.
It's not implemented yet, but in the meantime I've released an extensible Mixins library for Dart which includes a port of the popular Underscore.js functional utility library: https://github.com/mythz/DartMixins