关于继承:Dart – 如何使用特定的构造函数扩展 Map?

Dart - How to extend Map with a specific constructor?

我想用一个数据库表的抽象类扩展 Darts 映射,然后必须为每个表扩展它(参见下面的完整示例)。抽象类有一个构造函数,它已经设置了一些条目,但没有显式调用其超类中的任何构造函数。

问题是创建子类并直接设置条目(如map允许)。

我已尝试正确遵循此答案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
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 = '[\
';
    list.forEach((element) {
      out = out + _indent;
      print('_printList( element=$element is ${element.runtimeType}');
      if (element is Map) {
        out = out + _prettyPrintMap(element, depth) + ',\
';
      } else if (element is List) {
        out = out + _prettyPrintList(element, depth) + ',\
';
      } else {
        out = out + element.toString() + ',\
';
      }
    });
    depth--;
    return out + ']';
  }

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

你的 TableMap 类不是 extend Map,它是 implement。因此,您不调用 Map 的构造函数 - 这似乎是正确的方法。

如果你想在构造时填充你的数据保存 Map _inner,你可以在你的构造函数中这样做;你现在的做法看起来不错,或者你可以在构造函数中完全初始化你的变量。

当然,您不能只为自定义实现使用文字语法——文字基本上绑定到默认的 Map。但是您可以添加一个构造函数,该构造函数接受一些值并将这些值传递给您的私有基类构造函数,然后将值添加到 _inner.

例如,您可以添加(类似于 Map 接口):

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

然后使用它:

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

同样,您可以将 MapIterable 添加到 TableMap 类的现有或新构造函数中,并在构造过程中传递数据。