0

以前は次のコードがありましたが、正常に動作します。(Card、SearchResults、Quiz はすべて Persistable を拡張し、Persistable にはコンストラクターが含まれていることに注意してください.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);
  }
}

少し長くなってしまったので、2回に分けて書きたいと思います。私は最初にこれを持っています:

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

合理的に思えますが、メソッドを再定義しようとすると混乱します。

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は実際には class のインスタンスを意味しますPersistablelookup値が class になるようにマップを入力して、それらのコンストラクターPersistableを呼び出すにはどうすればよいですか?.fromMap

4

1 に答える 1

2

まず第一に、あなたの最初のアプローチは完全に有効であり、単にその冗長さのために捨てるべきではないと思います. 代替アプローチは複雑さが増し、動的ディスパッチが本当に必要な場合にのみ正当化されると思います。(たとえば、永続化のためにライブラリを作成し、ライブラリのクライアントの永続化のために任意のクラスを登録する機能を追加したい場合)動的ディスパッチが必須である場合、主に2つの可能性があると思います: - リフレクションAPI。最近、リフレクション ライブラリに同期 API が追加されたため、この方法は以前よりもはるかに手頃な価格になりました。とにかく、リフレクションによって発生するコストは常にあると思います。- コア DART 機能を使用します。

2 番目のアプローチでは、ある種のトリックを使用して、コンストラクターの呼び出しを動的に模倣することができます。たとえば、タイプ変数ではなく、必要なクラスのインスタンスを返す関数をマップに格納できます。

したがって、コードは次のようになります

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);
}

そしてクライアント側で:

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

(注意 - 私はこれをテストしませんでした) https://github.com/vadimtushko/objectoryでそのアプローチのサンプル コードを探すことができます。

于 2013-04-24T08:39:56.330 に答える