BajaBob
BajaBob

Reputation: 2853

Dart Abstract class of Generic Type with Named Constructor

I am attempting to construct an abstract class that requires a named constructor in Dart. Given some Map (m), this generic type must be able instantiate itself.

The Dart compiler is throwing T.fromJson -> Invalid constructor name.

My attempt at coding this:

abstract class JsonMap<T> {
  Map toJson();
  T.fromJson(Map m);
}

Upvotes: 8

Views: 5838

Answers (3)

A. L. Strine
A. L. Strine

Reputation: 651

Untested, but off the top of my head, you should write your code like so:

abstract class JsonMap<T> {
  Map<String, dynamic> toJson();
  T fromJson(Map<String, dynamic> m);
}

The dot makes fromJson(Map m) a constructor of type T, or a static function belonging to type T. Without the dot, it is a function belonging to the abstract class JsonMap, returning type T. Specifying the map type is good practice if you know what it will be (like with json).

Upvotes: 0

jamesdlin
jamesdlin

Reputation: 89936

You're creating a class named JsonMap that is parameterized on type T. T is not the name of your class, so T.fromJson is not a valid named constructor for JsonMap.

If you want JsonMap to have a named constructor, it should be JsonMap.fromJson(Map m).

Upvotes: 1

Durdu
Durdu

Reputation: 4849

I struggled with the same concept (in the same place ... API parsing :)) ) and I didn't found a proper solution.

But maybe you can use something this thing I found while checking block pattern this (I am not using it for my model part):

abstract class SomeBase {
  void load();
}

class Provider<T extends SomeBase> extends InheritedWidget {
  final T something;

  Provider({
    Key key,
    @required this.something,
  }): super(key: key);

  @override
  bool updateShouldNotify(_) {
    return true;
  }

  static Type _typeOf<T>() => T;

  static T of<T extends SomeBase>(BuildContext context){
    final type = _typeOf<Provider<T>>();
    Provider<T> provider = context.inheritFromWidgetOfExactType(type);
    return provider.something;
  }
}

OR just use this without encapsulating it in an inherited widget and provide the already initialised objects (like user or whatever you are parsing) that just load the values from the JSON provided.

Upvotes: 5

Related Questions