I was trying to create a class for questions so that I can use it in main.dart file in my Quiz App but I encountered some errors. Please tell me Why these errors came and How can I resolve them?
class Question:
class Question {
String questionText;
bool questionAnswer;
Question({String q, bool a}) {
questionText = q;
questionAnswer = a;
}
}
Errors:
Non-nullable instance field 'questionAnswer' must be initialized.
Non-nullable instance field 'questionText' must be initialized.
The parameter 'q' can't have a value of 'null' because of its type, but the implicit default value is 'null'.
The parameter 'a' can't have a value of 'null' because of its type, but the implicit default value is 'null'.
Image of Errors here.
The issue is about null-safey, you need to make fields nullable, late or add required on constructor.
class Question {
late String questionText;
late bool questionAnswer;
Question({required String q, required bool a}) {
questionText = q;
questionAnswer = a;
}
}
class Question {
String questionText;
bool questionAnswer;
Question({required this.questionAnswer, required this.questionText});
}
Find more about -null-safety
Yeasin's answer is probably what you want, but I want to expand on null safety.
so dart, the underlying language, now has something called "null safety".
This means that unless you tell dart the variable can be null, it will complain when a non-nullable variable is not given a variable.
Example
class Question{
String complaint; // complain because it is not initialised
String fine = ""; // no complaint, because we have a string variable, though it is empty.
late String lateString; // tells the compiler don't worry. I'll define it later in the constructor while the object in being created
String nullable?; // tells the compiler this variable can be null
}
using variables that can be null comes with a host of other things to think about. so I advise looking into it. I've linked a really easy video on the topic (depending on your skill you might be okay to find a faster video)
https://www.youtube.com/watch?v=llM3tcpaD5k
Related
I have a question i flutter
in some named parameters like color :
Or physics : in listviewbuilder the value is Colors.some color name in color and
Neverscroll in physics
My question is how to know that the attribute take this value although I tried to search in source code in flutter but i couldn't find out how
Thanks a lot
Theses are known as named constructor. Check this class
class MyClass {
final int a;
final String b;
final double c;
MyClass({required this.a, required this.b, this.c = 1.0});
}
Once you like to use this class you need to provide data like
MyClass(a: 1, b: "");
Note here a and b are required but c is using default value. Also, you can make nullable variables.
A good start guide will be language-tour
Im using some code from a tutorial but putting it in my own app. I cant figure out the next warning and how to solve:
LateInitializationError: Field ‘_durationRemaining#585382383’ has not been initialized.
The code(piece of the whole code) where this error is from is:
late MapBoxNavigation _directions;
late MapBoxOptions _options;
bool _isMultipleStop = false;
late double _distanceRemaining, _durationRemaining;
late MapBoxNavigationViewController _controller;
bool _routeBuilt = false;
bool _isNavigating = false;
#override
void initState() {
super.initState();
initialize();
}
The error is about the rule:
late double _distanceRemaining, _durationRemaining;
Am i doing something wrong? Maybe because i have 2 fields behind the late double and not the right way?
If i delete the Late in front of double, then get this errors:
lib/main.dart:42:10: Error: Field ‘_distanceRemaining’ should be initialized because its type ‘double’ doesn’t allow null.
double _distanceRemaining, _durationRemaining;
^^^^^^^^^^^^^^^^^^
lib/main.dart:42:30: Error: Field ‘_durationRemaining’ should be initialized because its type ‘double’ doesn’t allow null.
double _distanceRemaining, _durationRemaining;
When defining any variable as late, it must be initialized with the specified type before accessing it. In your case, it should be initialized in the initState() function. If you don't want to use the late keyword, you could make your variable nullable by using the ? operator.
For Eg
double? _distanceRemaining, _durationRemaining;
This would make your double variable nullable meaning it could accept null values.
If I do that I get:
264:60: Error: Operator '/' cannot be called on 'double?' because it is potentially null.
? "${(_durationRemaining / 60).toStringAsFixed(0)} minutes"
272:60: Error: Operator '*' cannot be called on 'double?' because it is potentially null.
? "${(_distanceRemaining * 0.000621371).toStringAsFixed(1)} miles"
The code there is:
? "${(_durationRemaining / 60).toStringAsFixed(0)} minutes"
? "${(_distanceRemaining * 0.000621371).toStringAsFixed(1)} miles"
I have to change something there also I guess. Because there it cant be null?
When a variable is nullable, you are restricted to using the normal operations and function calls that can be used on non-nullable variables.
For eg
double? _durationRemaining;
var x = _durationRemaing + 10;
You cannot do this operation because _durationRemaing can be null. For this, you can use the ?? operator, which checks whether the variable is null or not.
var x = (_durationRemaing ?? 0) + 10;
This means that if the variable is null use 0 as the value. So you have to use the ?? operator in your code mentioned above.
I think in new Dart rules the variables can not be declared/initialized as null. So we must put a late keyword before the variable type like below:
late String id;
Or a ? mark after the variable type like below:
String? id;
Are these two equal Or there are some differences?
A nullable variable does not need to be initialized before it can be used.
It is initialized as null by default:
void main() {
String? word;
print(word); // prints null
}
The keyword late can be used to mark variables that will be initialized later, i.e. not when they are declared but when they are accessed. This also means that we can have non-nullable instance fields that are initialized later:
class ExampleState extends State {
late final String word; // non-nullable
#override
void initState() {
super.initState();
// print(word) here would throw a runtime error
word = 'Hello';
}
}
Accessing a word before it is initialized will throw a runtime error.
when you use late keyword you can't let variable uninitialized when you called it with ? allows to you let variable uninitialized when you create it and call it
Null safety rules doesn't mean you can't use null. You can, but you should indicate that a variable might have the value null, by add "?" to its type declaration.
By use keyword late you indicate that variable has a non-nullable type, is not initialized yet, but will be initialized later.
Exception is thrown if try to acсess value of late variable before initialization.
I'm having trouble understanding how to type promote an object's field if it is nullable. Let's say I had the following Comment class and tried to access its one nullable field:
class Comment {
final String? text;
Comment(this.text);
}
void main() {
final comment = Comment("comment");
if (comment.text!= null) {
String text = comment!.text;
}
}
The Dart compiler would give me an error for trying to assign a nullable variable to a non-nullable variable. From what I've gathered from looking into this topic, it's impossible to have type promotion with instance variables because instance variables can be modified which can then break the sound null-safety. I've seen the Null assertion operator (!.) being used in these circumstances, however it doesn't seem to work with fields, only with methods.
With dart null-safety, how should I go about assigning a nullable field such as String? to a non-nullable variable (String). To the same effect, how should I go about passing a nullable field to a function that requires a non-null argument.
You can fix it in different ways:
Use local variable (recommended)
final local = comment.text; // <-- Local variable
if (local != null) {
String text = local;
}
Use ?. and provide a default value
String text = comment?.text ?? 'Default value';
Use Bang operator !
if (comment.text != null) {
String text = comment.text!; // <-- Bang operator
}
Note: Bang operator can result in a runtime error if the text was null.
I don't really understand how required works. For example I've seen this code:
class Test{
final String x;
Test({
required this.x
});
factory Test.initial(){
return Test(x: "");
}
}
But what should required do here? Seems like it makes an optional parameter a non optional parameter.
Update
As of Dart 2.12, the required keyword replaces the #required meta annotation. For detailed info look into the official FAQ. The following answer has been updated to reflect both this and null safety.
Parameters required by default
The parameters of a class constructor or function are required by default.
class Test {
final String x;
Test(this.x);
}
You're not allowed to do this:
final value = Test();
// 1 positional argument(s) expected, but 0 found.
You must do this:
final value = Test('hello');
Optional named parameters
If you surround a parameter with curly braces, though, in addition to becoming a named parameter, it also becomes optional.
Since it's optional, the property must either be nullable like this:
class Test {
final String? x;
Test({this.x});
}
Or it has to have a default value like this:
class Test {
final String? x;
Test({this.x = ''});
}
So now this is ok:
final value = Test();
And so is this:
final value = Test(x: 'hello');
Required named parameters
Sometimes you don't want to allow a parameter to be null and there is no natural default variable. In that case you can add the required keyword in front of the parameter name:
class Test {
final String x;
Test({required this.x});
}
This is not ok anymore:
final value = Test();
// The named parameter 'x' is required, but there's no corresponding argument.
But this is still fine:
final value = Test(x: 'hello');
Dart 2.12 (null safety):
Beginning with Dart 2.12, the #required annotation is now replaced by the required keyword. You should mark your field required if it is mandatory for others to pass some value to it.
For example:
class Foo {
final int a; // Mandatory? Use 'required'
final int b; // Not mandatory? Don't use 'required'
Foo({
required this.a, // Marked 'required'
this.b = 1,
});
}
Usage:
Foo(); // Error: 'a' is required
Foo(a: 0); // Good
Foo(a: 0, b: 1); // Good
#required is an annotation that will create a warning for you to remember that the named parameter is necessary for the class to work as expected.
It will not create compile errors, at least for what I know.
#required bounds you to pass #required marked arguments while creating object of Class. For example, while showing a dialog, you'd mark context as required since, you cannot show dialog without having a valid context. But, you should not overuse it.
Short answer: Named parameters are optional by default in Dart. We prefer them to positional params for ease of use. In this case, the named parameters also might be expected to hold some value all the time (non-nullable) - from initialization itself. Hence, the double effort.
He could use default value initialization of the parameters instead of 'required', if the values were compile-time constants, and that doesn't seem to be the case here.
Positional parameters can be required or optional, which we pass in order when calling. The following is an example of required positional parameters' usage:
class Object{
String name;
int value;
Object(this.name, this.value=100); //auto type inference
}
final one = Object("Name here", 50); // All parameters are needed to call.
Named parameters are another type of optional parameters. Flutter APIs use named parameters and in our UI code, it is preferred to use named parameters instead of positional parameters. Reason being readability and clarity when reading code or calling the constructors later on at several parts of the code. You would have seen this as the case with all Widgets, Styles. For if it were to be positional it would be difficult to keep track of them upon calling with the sheer amount of methods that would be in use, and dynamic type inference could also be at work.
void display({required String name, int value1, int value2=100}) {...;} //named params
display(value1: 50, name: "Calculated name");
NOTE:
If exists, required positional parameters have to come first. Either named or optional positional params can follow(NOT BOTH).
String say(String from, String msg, [String? device]) { //req. pos params and opt pos params.
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}
assert(say('Bob', 'Howdy') == 'Bob says Howdy');
Remove
required
in constructor.
Instead write
final String? x;
So, it becomes as:
class Test{
final String? x;
Test({
this.x
});
factory Test.initial(){
return Test(x: "");
}
}