4

I am trying to lazy-load data from the server into a Map.
For that reason I would like to add functionality to Map, so that when a key doesn't exist, a call is done to get the value.

What I tried is this:

class LazyMap extends Map {
  // use .length for now. When this works, go use xhr
  operator [](key) => LazyMap.putIfAbsent(key, () => key.length);
}

LazyMap test = new LazyMap();

main() {
  print(test.containsKey('hallo')); // false

  // I prefer to use this terse syntax and not have to use putIfAbsent
  // every time I need something from my map
  print(test['hello']); // 5

  print(test.containsKey('hallo')); // true
}

This raises an error stating "Cannot resolve constructor Map for implicit super call" which is cryptic for me.

This is the first time I try to extend anything, so I might be doing stupid things. Any advise on doing this better, or probably telling me that I am using a bad practice will be appreciated.

I've looked into this answer: How do I extend a List in Dart, but this is about extending a List, not a Map. I've looked for a MapBase but could not find one.
And I've looked into this answer: I want to add my own methods to a few Dart Classes, but this seems to be a very old answer with no real solution.

Kind regards, Hendrik Jan

Community
  • 1
  • 1
Hendrik Jan
  • 4,396
  • 8
  • 39
  • 75

3 Answers3

7

You should have looked at the other answer of How do I extend a List in Dart? ;) In this answer I point to DelegatingList. Next to it there's DelegatingMap.

You can use DelegatingMap as superclass or as mixin to do what you want :

import 'package:quiver/collection.dart';

class LazyMap extends DelegatingMap {
  final delegate = {};

  operator [](key) => putIfAbsent(key, () => key.length);
}

Note that you will not be able to use this with xhr because xhr is asynchronous.

Community
  • 1
  • 1
Alexandre Ardhuin
  • 71,959
  • 15
  • 151
  • 132
  • Hi Alexandre. I did see your answer and it looks useful. Until I am more experienced in using Dart, I prefer to use "stock" dart and not use external libraries. With libraries I am not sure that the same libraries are still around in a couple of years. I might look into quiver to see how it is written. – Hendrik Jan Jan 13 '14 at 19:50
  • 1
    _pub.dartlang.org_ will never remove existing packages. So you can use _packages_ without fear. – Alexandre Ardhuin Jan 13 '14 at 19:57
  • That is good to know. In Javascript there are a lot of libraries that are not being maintained or of low quality. Is there any guarantee about maintenance and quality of Dart pub packages? Or is it up to the user to decide if he/she thinks the quality is high enough? (or should this be a new SO question?) – Hendrik Jan Jan 14 '14 at 12:20
  • I think this could be a great SO question! – Alexandre Ardhuin Jan 14 '14 at 12:59
5

Looking at this post, you cannot extends Map and its subclass. I think the best way to get what you want is to implement it.

class LazyMap implements Map {
  Map _inner = {};

  operator [](key) => _inner.putIfAbsent(key, () => key.length);

  // forward all method to _inner
}
Faris Nasution
  • 3,450
  • 5
  • 24
  • 29
  • Hi Faris. The link you posted is not working. It points to your own gmail inbox which of course doesn't work for me. Could you edit the link? Other than that, this is a very useful answer. I would have liked to hear otherwise, but I'll have to contend with implementing it seems. – Hendrik Jan Jan 13 '14 at 07:45
  • Is there an example where all methods are forwarded to _inner? I'm not sure about the correct syntax in each of them. – Jemolah Jun 04 '20 at 07:56
0

My solution:

import 'package:quiver/collection.dart';

class MapDefault<K, T> extends DelegatingMap<K, T> {
  final delegate = {};
  final T defValue;

  MapDefault(this.defValue);

  @override
  T operator [](Object? key) => delegate[key] ?? defValue;
}