I created a model class, this is one of my a variable in model class
Datetime hotel_effect_open_date
but JSON response hotel_effect_open_date is null, getting an error in my application. and I modified to DateTime to String, it's working. In API created in the .net core, it looks like this,
Nullable<DateTime> hotel_effect_open_date
How to create a nullable variable in DART language?
Now Dart is in the process of redesigning its type system. So that expression of that type can be either nullable or non-nullable. Something like this:
type? variable; // variable can be null.
Example:
int? a; // a can now be null.
Reference: Dart nullability syntax decision
TLDR:
int? aNullableInt = null;
Detailed explanation:
Dart 2... and above
documentation:
https://dart.dev/null-safety
With null safety, all of the variables in the following code are
non-nullable:
// In null-safe Dart, none of these can ever be null.
var i = 42; // Inferred to be an int.
String name = getFileName();
final b = Foo();
To indicate that a variable might have the value null, just add ? to
its type declaration:
int? aNullableInt = null;
Dart <2
DateTime example;
example = null;
Uninitialized variables have an initial value of null. Even variables with numeric types are initially null, because numbers—like everything else in Dart—are objects.
int lineCount;
assert(lineCount == null);
Related
This question already has answers here:
What is Null Safety in Dart?
(2 answers)
Closed 1 year ago.
After defining a map (with letters as keys and scrabble tile scores as values)
Map<String, int> letterScore //I'm omitting the rest of the declaration
when I experiment with this function (in DartPad)
int score(String aWord) {
int result = 0;
for (int i = 0; i < aWord.length; ++i) {
result += letterScore[aWord[i]];
}
return result;
}
I consistently get error messages, regardless of whether I experiment by declaring variables as num or int:
Error: A value of type 'int?' can't be assigned to a variable of type
'num' because 'int?' is nullable and 'num' isn't [I got this after declaring all the numerical variables as int]
Error: A value of type 'num' can't be returned from a function with
return type 'int'.
Error: A value of type 'num?' can't be assigned to a variable of type
'num' because 'num?' is nullable and 'num' isn't.
I understand the difference between an integer and a floating point (or double) number, it's the int vs int? and num vs num? I don't understand, as well as which form to use when declaring variables. How should I declare and use int or num variables to avoid these errors?
Take this for example:
int x; // x has value as null
int x = 0; // x is initialized as zero
Both the above code are fine and compilable code. But if you enable Dart's null-safety feature, which you should, it will make the above code work differently.
int x; // compilation error: "The non-nullable variable must be assigned before can be used"
int x = 0; // No Error.
This is an effort made from the compiler to warn you wherever your variable can be null, but during the compile time. Awesome.
But what happens, if you must declare a variable as null because you don't know the value at the compile time.
int? x; // Compiles fine because it's a nullable variable
The ? is a way for you tell the compiler that you want this variable to allow null. However, when you say a variable can be null, then every time you use the variable, the compiler will remind you to check whether the variable is null or not before you can use it.
Hence the other use of the ?:
int? x;
print(x?.toString() ?? "0");
Further readings:
Official Docs: https://dart.dev/null-safety/understanding-null-safety
Null-aware operators: https://dart.dev/codelabs/dart-cheatsheet
I've created my class in Dart this way, but I'm getting the Non-nullable instance field 'text' must be initialized. Try adding an initializer expression, or add a field initializer in this constructor, or mark it 'late'. I would like to know if there's a way to do it in a 'Python' style where this kind of class creation is possible, thank you in advance.
class Lexer {
String _text;
int _pos;
String _current_char;
Lexer(String text) {
this._text = text;
this._pos = -1;
this._current_char = '';
this.advance();
}
void advance() {
this._pos++;
this._current_char = this._pos < this._text.length ? this._text[this._pos] : '';
}
}
class Lexer {
String _text;
int _pos;
String _current_char;
This declares several members with type String. Since they are declared as String and not as String?, these members are non-nullable; they are not allowed to ever be null. (This is part of the new null-safety feature from Dart 2.12.)
Dart initializes objects in two phases. When the constructor's body runs, Dart expects all member variables to already be initialized. Because your members are non-nullable and haven't been initialized to non-null values yet, this is an error. The error message explains what you can do:
Non-nullable instance field 'text' must be initialized. Try adding an initializer expression, or add a field initializer in this constructor, or mark it 'late'.
Use initializer expressions. This means using an initializer list:
Lexer(String text)
: _text = text,
_pos = -1,
_current_char = '' {
advance();
}
Note that if you're initializing members with a construction parameter of the same name, you can use shorthand:
Lexer(this._text)
: _pos = -1,
_current_char = '' {
advance();
}
Adding field initializers. This means initializing members inline in the class declaration.
class Lexer {
String _text = '';
int _pos = -1,
String _current_char = '';
Marking your members as late. This means that you promise that the variables will be initialized before anything attempts to use them.
class Lexer {
late String _text;
late int _pos,
late String _current_char;
Making your members nullable, which allows them to be implicitly null by default:
class Lexer {
String? _text;
int? _pos,
String? _current_char;
However, that will require that all accesses explicitly check that the members aren't null before using them.
You also might want to read: Dart assigning to variable right away or in constructor?
class A {
final int? b; // Error
}
Error:
The final variable 'b' must be initialized.
Since the field b is nullable, it could be left uninitialised and hence needs no initialisation work. But it gives an error.
Not initializing a final field, regardless of whether it's nullable, is almost certainly a mistake. This was not different before null safety was introduced.
Suppose that final fields were allowed to be implicitly initialized to null. Then in a class such as:
class A {
final int? b;
}
there would be no point for b to exist at all since it'd always be null.
But maybe A provides a constructor that could initialize b to a non-null value:
class A {
final int? b;
A();
A.nonNull() : b = 42;
}
But now there's no way to tell if the default A() constructor actually wants b to be initialized to null or if the programmer just forgot to initialize it. The latter is much more likely, so Dart errs on the side of requiring explicit initialization.
You need to initialize b first like int b or string b; Assigning value is optional.
Is there any way to get this to return "default" without writing out special functions to check the argument and set it?
void main() {
Thing stuff = Thing(text: null);
print(stuff.text);
}
class Thing{
String text;
Thing({this.text: "default"});
}
I have a map coming in from Firebase and sometimes values will be null and I'd like my class to use its default values when it is provided null.
Thing({text}) : this.text = text ?? 'default';
You will need to add this small snippet because default values in constructors only work if there is no value specified.
The ?? null-aware operator will only use the 'default' value if the value that is being passed is actually null (which will also be the case if no value is specified).
I've recently came across this question How do I solve the 'Failed assertion: boolean expression must not be null' exception in Flutter
where the problem comes from a should be invalid code that gets treated as valid.
This code can be summarized as :
int stuff;
if (stuff = null) { // = instead of ==
}
But why does this code compiles ? As the following will not.
int stuff;
if (stuff = 42) {
}
With the following compile error :
Conditions must have a static type of 'bool'.
So I'd expect out of consistency that if (stuff = null) to gives the same error.
null is a valid value for a bool variable in Dart, at least until Dart supports non-nullable types.
bool foo = null;
or just
bool foo;
is valid.
Therefore in the first case there is nothing wrong from a statical analysis point of view.
In the 2nd case the type int is inferred because of the assignment, which is known to not be a valid boolean value.
bool foo = 42;
is invalid.
When you say var stuff; with no initial value it is giving stuff a static type of dynamic. Since dyamic might be a bool, it's legal to assign null to a variable of type dynamic, and it's legal to use a possibly null bool in a conditional, the compiler doesn't flag this. When you say int stuff; the compiler knows that stuff could not be a bool. The reported error in that case is cause by the static type of stuff, not the assignment to null.
Edit: Got the real answer from someone who knows how to read the spec.
The static type of an assignment expression is the right hand side of the assignment. So the expression stuff = null has the static type of Null which is assignable to bool.
The reasoning is that the value of an assignment is the right hand side, so it makes sense to also use it's type. This allows expressions like:
int foo;
num bar;
foo = bar = 1;
Commonly assignment operation returns the value that it assigns.
int a = 0;
print(a = 3);//Prints 3
So,
When stuff = null,
'stuff = null' returns null. if statement needs a boolean .null is a sub-Type of boolean.
if(null){}
is valid
When stuff = 42,
'stuff = 42' returns 42. if statement needs a boolean .42 is not a sub-Type of boolean.
if(42){}
is not valid