I suppose you're trying to make your code more maintainable by replacing your current Map
with something else, which you refer to as object
.
I also suppose that by object
you mean Dart classes with typed fields.
If you want to continue to be able to find "objects" by their String names, you cannot avoid using a Map
.
If the "keys" are all known at compile-time (ie. before your program actually runs) then you can used typed objects, which is what you should prefer as it makes reasoning and organizing code much easier.
Let's say you know that your Map will only ever have keys a
and b
with types A
and B
, respectively. Then you can replace your Map easily:
class A {}
class B {}
class MyClass {
final A a;
final B b;
MyClass(this.a, this.b);
}
Simple.
If some "keys" may not be present, just turn them into nullable values:
class A {}
class B {}
class MyClass {
final A? a;
final B? b;
// passing a or b is now optional!
MyClass({this.a, this.b});
}
If you don't know what the keys will be at all, then there's no way around using a Map
. That's what they are for.
With Dart support for dynamic typing, you could "assume" certain keys will have certain types, though. So, while this is normally bad for code maintenance due to the impossibility to analyze this before the program runs (ie. it may crash at runtime), you could do something like this:
class Foo {
final String a;
Foo(this.a);
String toString() => 'Foo($a)';
}
class Bar {
final String a;
Bar(this.a);
String toString() => 'Bar($a)';
}
// example usage
void main() {
Map<String, dynamic> map = {'foo': Foo('a foo')};
Foo foo = map['foo'];
print(foo); // ok!
Bar? bar = map['bar'];
print(bar); // null
}
Hopefully this helps clarify when you should use an "object" and when you need to use a Map.