Variables
Specifiers
Types
Flutter is statically type, therefore, all types are evaluated at compile time, this can be explicitly defined as:
String text = "hello";
int number = 22;
However, Flutter also provides a implicit declaration (var
) that can be determined by compiler, an example being:
var text = "hello";
var number = 22;
Another way of implicit definition is declaring as Object
class, since all types in Dart inherits from the Object
type, implicit definitions can be written as:
Object text = "hello";
Object number = 22;
One exception is that Flutter also allow dynamic typing, if a declarator dynamic
is used, the evaluation will happen at runtime:
dynamic text = "hello";
dynamic number = 22;
The best practice is here is to avoid usage of dynamic
and Object
declaration, always use var
or explicit typing.
Mutation Specifier
final
specifier
Variables with final
specifier is instantiated once and will prevent mutation afterwards, usually the instantiation is performed when calling the constructor:
class Foo extends StatelessWidget {
const Foo({
super.key,
required this.text,
required this.number
});
final String text;
final bool number;
}
In the example, both text
and number
are required
to be instantiated during the constructor call:
void main(){
Foo body = Foo(
text: "hello",
number: 22
)
}
After the instantiation, the variables cannot be mutated, upon mutation, a compile time error will appear.
const
specifier
Variables with const
specifier are required to be evaluated at compile time, meaning the value cannot be mutated by any event in runtime including a constructor call.
const String text = "hello",
const int number = 22
Nullable specifier
Variables are required to be defined at declaration by default, to enable the option for the variable to be null
, the ?
specifier should be used:
String? text;
int? number;
Accessing Null Variables
When a variable is null, and the compile time null check for the variable is disabled by the nullable specifier, null will be treated as a absense of value and therefore can perform instantiation checks with null:
int? value; // initialized to 'null'
// This null-check ensures that 'value' is not 'null'
if (value != null) {
doSomething(value);
}
Assigning nullable values
Assigning nullable values to non-nullable types will generate a compile time error:
String? world(){
return "hello"
}
void main(){
int? text = world();
int text = world(); // compile time error
}
late
specifier
To allow top-level variables and class variables to be initialize separately to their declaration, the late
specifier can be used, an example being:
late String text;
void main(){
text = "hello";
print(text);
}
When accessing a late
specified variable without instantiation at runtime, a runtime exception will be thrown (runtime error):
late String text;
void main(){
print(text); // Runtime exception
text = "hello";
}
The best practice of nullability and mutability is to follow the order of const
>> final
>> var
with no nullability specifier >> final late
>> var?
. Also non const top-level variables should be avoided.
Data Types
Built-in Data Types
Dart does not have primitive data types as all types are interfaces inherited from Object
class
Number Types
Only two number types exists in Dart, int
and double
. int
can represents integers up to 64 bits due to JavaScript limitation. double
follows the IEEE 754 standard and is also 64 bits.
These numbers are inherited from the num
class, with operations and methods such as abs()
, floor()
, etc. Note that num
, double
, int
cannot be extended.
String Literals
Only one String type exists in Dart, String
, which holds a sequence of characters specify in UTF-16 code. Within String declarations ""
, ${ \\ expression }
can be declared, and any expression that can evaluates to String can be placed within. A raw String
can be created with declarator r
infront of the string:
String Concatenation
As with many other languages, concatenation with +
cause a new String instance to be created, writing to a StringBuffer
will prevent this process, therefore its recommended, an example is shown bellow.
Instead of:
var text = '';
for(var i = 0; i < 100000; ++i) {
text += '$i, \n';
}
print(text);
Using StringBuffer
:
final text = StringBuffer();
for(var i = 0; i < 100000; ++i) {
text.writeln('$i, ');
}
print(text.toString());
Booleans
Dart booleans are still interfaces that inherits Object
, and only alow true
and false
assignment. 1
and 0
are not allowed.
Enums
Dart enum
are non-inheritable classes that holds a fixed number of constant values. All enum
extends from the Enum
class automatically when declared. Differ from enums in other languages like C++, Dart enums can hold fields, methods and const constructors. An example of enum:
Records
Records in Dart are ordered group of named elements, similar to tuple in C++