簡體   English   中英

Dart - 如何使用特定的構造函數擴展 Map?

[英]Dart - How to extend Map with a specific constructor?

我想用抽象的 class 擴展 Darts map 用於數據庫表,然后必須為每個表擴展(參見下面的完整示例)。 抽象 class 有一個構造函數,它已經設置了一些條目,但沒有顯式調用其超級 class 中的任何構造函數。

問題是創建子類並直接設置條目(如 map 允許)。

我試圖正確地遵循這個答案

import 'package:uuid/uuid.dart';

void main(List<String> args) {
  Map<String, dynamic> map = {
    'key': 99,
  };
  SomeTable one = SomeTable();
  print('$one with ${one.length} entries -> ${one.prettyPrint()}');
  SomeTable another = SomeTable();
  one['child'] = another;
  print('$one with ${one.length} entries -> ${one.prettyPrint()}');
  SomeTable third = {
    'key': 17,
  };
}

class SomeTable extends TableMap {
  SomeTable() : super('sometable');
  void someSpecificFunction() {}
}

abstract class TableMap implements Map<String, dynamic> {
  final Map _inner = <String, dynamic>{};

  static const String id = 'id', // 64bit
      uuid = 'uuid',
      identifier = 'identifier', // String "$tablename:$id"
      tablename = 'tablename';

  /// Constructor
  TableMap(String _tablename) {
    String uuidAsString = Uuid().v4();
    _inner[uuid] = uuidAsString;
    _inner[identifier] = tablename + ':' + uuidAsString;
    _inner[tablename] = _tablename;
  }

  /// Returns `true` if `ìd` = `null`
  bool get isNew => ([id] == null) ? true : false;

  @override
  operator [](Object key) {
    return _inner[key];
  }

  @override
  void operator []=(String key, value) {
    _inner[key] = value;
  }

  @override
  void addAll(Map<String, dynamic> other) {
    _inner.addAll(other);
  }

  @override
  void addEntries(Iterable<MapEntry<String, dynamic>> newEntries) {
    _inner.addEntries(newEntries);
  }

  @override
  Map<RK, RV> cast<RK, RV>() {
    return _inner.cast<RK, RV>();
  }

  @override
  void clear() {
    _inner.clear();
  }

  @override
  bool containsKey(Object key) {
    return _inner.containsKey(key);
  }

  @override
  bool containsValue(Object value) {
    return _inner.containsValue(value);
  }

  @override
  Iterable<MapEntry<String, dynamic>> get entries => _inner.entries;

  @override
  void forEach(void Function(String key, dynamic value) f) {
    _inner.forEach(f);
  }

  @override
  bool get isEmpty => _inner.isEmpty;

  @override
  bool get isNotEmpty => _inner.isNotEmpty;

  @override
  Iterable<String> get keys => _inner.keys;

  @override
  int get length => _inner.length;

  @override
  Map<K2, V2> map<K2, V2>(
      MapEntry<K2, V2> Function(String key, dynamic value) f) {
    return _inner.map(f);
  }

  @override
  putIfAbsent(String key, Function() ifAbsent) {
    return _inner.putIfAbsent(key, ifAbsent);
  }

  @override
  remove(Object key) {
    return _inner.remove(key);
  }

  @override
  void removeWhere(bool Function(String key, dynamic value) predicate) {
    _inner.removeWhere(predicate);
  }

  @override
  update(String key, Function(dynamic value) update, {Function() ifAbsent}) {
    return _inner.update(key, update, ifAbsent: ifAbsent);
  }

  @override
  void updateAll(Function(String key, dynamic value) update) {
    _inner.updateAll(update);
  }

  @override
  Iterable get values => _inner.values;

  /// Creates a string by putting each entry on a separate line and
  /// prefixing it with spaces according to its depth within the map.
  String prettyPrint() {
    return _prettyPrintMap(this, 0);
  }

  static final String _spaces = '                                   ';

  String _prettyPrintList(List<dynamic> list, int depth) {
    depth++;
    String _indent = _spaces.substring(0, 2 * depth);
    String out = '[\n';
    list.forEach((element) {
      out = out + _indent;
      print('_printList( element=$element is ${element.runtimeType}');
      if (element is Map) {
        out = out + _prettyPrintMap(element, depth) + ',\n';
      } else if (element is List) {
        out = out + _prettyPrintList(element, depth) + ',\n';
      } else {
        out = out + element.toString() + ',\n';
      }
    });
    depth--;
    return out + ']';
  }

  String _prettyPrintMap(Map<dynamic, dynamic> map, int depth) {
    depth++;
    String _indent = _spaces.substring(0, 2 * depth);
    String out = '{\n';
    map.forEach((k, v) {
      out = out + _indent + k + ': ';
      if (v is Map) {
        out = out + _prettyPrintMap(v, depth) + ',\n';
      } else if (v is List) {
        out = out + _prettyPrintList(v, depth);
      } else {
        out = out + v.toString() + ',\n';
      }
    });
    depth--;
    return out + '}';
  }
}

您的TableMap class 沒有extend Map ,它implement了它。 因此,您不要調用Map的構造函數——這似乎是正確的方法。

如果你想在構造時填充你的數據保存Map _inner ,你可以在你的構造函數中這樣做; 你現在的做法看起來不錯,或者你可以在構造函數中完全初始化你的變量。

當然,您不能只為自定義實現使用文字語法 - 文字基本上綁定到默認的Map 但是您可以添加一個構造函數,該構造函數接受一些值並將這些值傳遞到您的私有基礎 class 構造函數中,然后將值添加到_inner上。

例如,您可以添加(類似於Map接口):

factory SomeTable.fromEntries(Iterable<MapEntry> entries) {
  final table = SomeTable();
  table._inner.addEntries(entries);
}

然后使用它:

SomeTable third = SomeTable.fromEntries({
  'key': 17,
});

同樣,您可以將MapIterable添加到TableMap class 的現有或新構造函數中,並在構造過程中傳遞數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM