Lets say I want to refactor my code so it's easier to read and I have an object property that is type of Map<String,AnotherObject or dynamic> what is the best way to convert this property to another object? When it is a map I can call the relevant object using its String key. If it becomes another object how would I call the one I want?
for example:
class A1{
Map<String,B1> property;
}
to:
class A1{
List<B2> property;
}
class B2{
String key;
B1 property;
}
In the example above in order to get the property I want I would have to filter the list where key = keyIwant, while if it is a map I can just call map[key]. Is there any effective way to convert a map to an object? Dart is the technology I use.
CodePudding user response:
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.