Dart: Which is a better practice? Using 'late' or constructor initializer list
Neither.
Use a default constructor that initializes the fields themselves and a factory constructor that handles deserializing the json
object:
class Favourite {
final int favouriteId;
Favourite({required this.favouriteId});
factory Favourite.fromMap(Map<String, dynamic> map) {
final favouriteId = json['favouriteId'];
assert(favouriteId != null && favouriteId is int);
return Favourite(
favouriteId: favouriteId,
);
}
}
The late
keyword can be a source of headache if you don't handle it properly, so in general don't use it unless you have to.
Cherryholme
Updated on December 28, 2022Comments
-
Cherryholme over 1 year
I am modelling a Dart class with the new null safety types in mind. I believe there are two effective ways to initialize non-nullable properties, calculated from a parameter.
For this example, we will use the Favourite class.
This class uses the initializer list in the constructor.
class Favourite { int favouriteId; Favourite({required this.favouriteId}); Favourite.mapFromJson(dynamic json) : this.favouriteId = json["favouriteId"]; }
This class uses the 'late' keyword.
class Favourite { late int favouriteId; Favourite({required this.favouriteId}); Favourite.mapFromJson(dynamic json) { this.favouriteId = json["favouriteId"]; } }
When would you use one over the other? Using 'late' feels risky. If I added another named constructor, the compiler would not complain about 'favouriteId' not being initialized.
Are there other options?
Thank you!
-
Andrej over 3 yearsAs far as I know, you should use the
late
keyword only when you really have to. So the constructor initializer list would be a better option.
-
-
Cherryholme over 3 yearsI am glad to hear that the 'late' keyword is not the option. The code did not feel robust. I tried this factory example, and it works, but I don't understand why. Why is Dart happy with the factory now? It is no longer complaining about 'favouriteId' not being initialized. If you have sources that explain this, I'd love to read it!
-
rmtmckenzie over 3 yearsA factory method is essentially a static method with slightly better syntax and some properties like using the class's generics & replacing an implicit constructor. Since those aren't needed you could easily write the above as
static Favourite mapFromJson(Map<String, dynamic> map) { ... }
. -
Abion47 over 3 years@rmtmckenzie I always prefer factory constructors over static "factory" methods if for no other reason than it makes the intention clear. Also, a factory constructor named
fromMap
will make it that much easier to make this class support deserialization via thejson_serialization
package if that becomes necessary. -
Abion47 over 3 yearsMarking a
dynamic
as nullable is redundant. -
rmtmckenzie over 3 years@Abion47 oh definitely - sorry I was unclear, that wasn't an argument against them, just trying to clarify what they were.