Skip to main content

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;
tip

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";
}
tip

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

warning

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.

info

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++

Functions

Lists

Sets

Maps

Symbols