Reputation: 53711
I have a class that I am creating that looks like this:
class Movie {
final String title, posterPath, overview;
Movie(this.title, this.posterPath, this.overview);
Movie.fromJson(Map json) {
title = json["title"];
posterPath = json["poster_path"];
overview = json['overview';
}
}
I am getting a warning that says that "The final variables 'overview', 'posterPath', & '1' more must be initialized. There are also warnings around each variable saying 'title' can't be used as a setter because it is final.
When I write the constructor using this syntax, the warnings go away:
Movie.fromJson(Map json)
: title = json["title"],
posterPath = json["poster_path"],
overview = json['overview'];
What exactly is going on here?
Upvotes: 4
Views: 7298
Reputation: 71853
Dart objects must be fully initialized before anyone gets a reference to the new object. Since the body of a constructor can access this
, the object needs to be initialized before entering the constructor body.
To do that, generative Dart constructors have an initializer list, looking similiar to C++, where you can initialize fields, including final fields, but you cannot access the object itself yet. The syntax:
Movie.fromJson(Map json)
: title = json["title"],
posterPath = json["poster_path"],
overview = json['overview'];
uses an initializer list (the list of assignments after the :
) to initialize the final instance variables title
, posterPath
and overview
.
The first constructor uses an "initializing formal" this.title
to directly put the parameter into the field.
The constructor
Movie(this.title, this.posterPath, this.overview);
is effectively a shorthand for:
Movie(String title, String posterPath, String overview)
: this.title = title, this.posterPath = posterPath, this.overview = overview;
Your constructor can combine all of these and a body:
Movie(this.title, this.posterPath, String overview)
: this.overview = overview ?? "Default Overview!" {
if (title == null) throw ArgumentError.notNull("title");
}
(A const constructor cannot have a body, but it can have an initializer list with some restrictions on the allowed expressions to ensure that they can be evaluated at compile-time).
Upvotes: 14
Reputation: 277677
Dart separates properties initialization from the constructor body.
A constructor has 3 parts :
Both the initialization and body parts are optional.
final
variables must be initialized on the first 2 parts. They cannot be initialized inside the body.
A full constructor will look like the following :
MyClass(int value)
: assert(value > 0),
property = value,
super();
{
print("Hello World");
}
The main purpose of this initializer part is for body-less constructors which allows const constructors, a dart specific feature. See How does the const constructor actually work? for more details on these.
Upvotes: 9
Reputation: 53711
I just found some documentation around this, & it seams that the second version with the :
is what's called the "initializer list" which allows you to initialize instance variables before the constructor body runs.
There is more detail around this in the documentation here.
Upvotes: 2