简体   繁体   中英

How do I dispatch a constructor on a class in Dart?

I previously had the following code, it works fine. (note that Card, SearchResults, Quiz all extend Persistable, and Persistable contains the constructor .fromMap .

Persistable fromString(String value){
  Map<String, dynamic> m = parse(value);

  switch(m['type']){
    case 'card':
      return new Card.fromMap(m);
    case 'searchresults':
      return new SearchResults.fromMap(m);
    case 'quiz':
      return new Quiz.fromMap(m);
  }
}

It was a bit wordy, so I thought I would break it down into two parts. I first have this:

static final Map<String, Persistable> lookup =
    {'card': Card,
     'searchresults': SearchResults,
     'quiz': Quiz };

Seems reasonable, but then when I try to redefine the method, I get confused.

Persistable fromString(String value){
  Map<String, dynamic> m = parse(value);
  String type = m['type'];
  Persistable p = lookup[type];
  ... Confused, this can't be right
  ... ultimately want to "return new p.fromMap(m)";
}

Persistable p really means a instance of class Persistable . How do I type my lookup map so that its values are of the class Persistable , so that I can call their .fromMap constructors?

First of all I think your initial approach is perfectly valid and should not be cast away owing simply to its verbosity. I believe alternative approaches introduce additional complexity and are justified only if you are really in need of dynamic dispatch. (For example if you write library for persistency and you wish to add ability to register arbitrary class for persistency for clients of library) If dynamic dispatch is a must for you I believe there is two main possibility: - Reflection API. Recently reflection library got sync API, so this way is now much more affordable then before. I believe there always will be some cost incurred by reflection anyway. - Use core DART functionality.

With the second approach you may use some sort of trick to imitate constructor call dynamically. For instance you may store in map not Type variable but function which returns instance of required class:

So your code may look something like

static final Map<String, Function> lookup = new Map<String, Function>
static void registerClass(String className, factory) {
    lookup[className] = factory;
}
static Persistable getInstance(String className, Map map){
    return lookup[className](map);
}

And on client side:

....
registerClass('quiz', (map)=> new Quiz.fromMap(map));
registerClass('card', (map)=> new Card.fromMap(map));

(Attention - I did not test this) You may look for working sample code for that approach in https://github.com/vadimtsushko/objectory

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM