Fluttering Dart

Built-In Data Types

Constantin Stan
Nov 8 · 6 min read
Built-in data types of Dart

Flutter projects can use both platform-specific and cross-platform code. The latter is written in Dart, and, in order to build Flutter apps, some basic knowledge of Dart is required.

This is the first article, in a series, named Fluttering Dart, that will help us grasp on some fundamental knowledge of the powerful programming language that brings Flutter to life.

The examples can be tried out, and played with, using DartPad.

Bellow, we’ll go through the built-in data types of Dart:

Type num (the supertype of int and double)

Numbers, in Dart, can be of 2 types:

  • integer - no larger than 64 bits (depends on the platform)
  • 64-bit double-precision floating-point (IEEE 754 standard)

Their supertype is type num.

All numbers are also objects and, each, have specific methods.

void main() {
int x = 4;
print(x.toRadixString(2) == '100');
double y = 19.861004;
print(y.toStringAsFixed(4) == '19.8610');
}

In the above example, we first define an int called x that gets the value 4 and then we make use of the int’s method toRadixString to get to x’s binary representation (as a String). We could’ve used, for example the hexadecimal base - 16 - instead of 2. The equality between the representation of 4 in the binary base is '100' is true, and that is what the print method will display.

Then we define a double called y and we give it also a value (19.8610). We then use the double’s built in function toStringAsFixed to get the only 4 fraction digits representation of y (also as a String). The equality is also satisfied and therefore the print method will display true again.


Type String

A String is a sequence of UTF-16 code units.

In order to create a string, we can use single ' or double " quotes (it doesn’t matter which of these, as long as we’re consistent across our code).

String interpolation is built-in in Dart. Expressions can be embedded into strings using the form ${expression}, and are evaluated when we use them. If the expression is an identifier, then we can omit the {}:

void main() {
String dartLang = 'Dart';
String javaLang = 'Java';
print('Saying that $dartLang is identical to $javaLang might be a bit too much... At least when we count the letters in their names we get ${dartLang.length} in both cases.');
}

Multi-line strings can be created using triple quotes (either single or double):

void main() {
String multiLine = '''
This
is
nice!
''';
print('$multiLine');
}

String concatenation is done simply by placing string literals next to each other without the + sign:

void main() {
String concatenated = 'This ''is ' '(kind ''of) '
'odd'
'...';
print('$concatenated');
}

Type bool

The bool type represents booleans.

It has only two values: true or false

Conditions like if, while or assert can be used only with bools.

Dart’s type safety means that you can’t use code like if(nonBooleanValue) or assert(nonBooleanValue). Instead, explicitly check for values, like this:

void main() {
String emptyName = '';
if(emptyName.isEmpty) {
print('Like the name says, it is empty!');
}
String nullName;
if(nullName == null) {
print('Like the name says, it is null!');
}
}

Type List

List is a commonly used collection type.

Arrays (for people coming from other programming languages) are List objects.

In the example bellow, both a List literal and a List constructor are used. It is recommended to use literals when possible:

void main() {
// the literal way
List oneWay = [1,2,3];
// the constructor way
List orAnother = List<int>(3);
}

Type Map

Map is another commonly used collection type.

In the example bellow, both a Map literal and a Map constructor are used. It is recommended to use literals when possible:

void main() {
// the literal way
Map oneWay = {'a': 0, 'b': 1, 'c': 2};
// the constructor way
Map orAnother = Map<String, int>();
}

Type Set

Sets, in Dart, are unordered collections of unique items.

To create an empty set, use {} preceded by a type argument, or assign {} to a variable of type Set.

The syntax for map literals is similar to that for set literals. Because Map literals came first to Dart, {} defaults to the this type. If you forget to add the type annotation on {} or you don't assign {} to a variable of type Set, then, by default, Dart creates an object of type Map<dynamic, dynamic>.

void main() {
// the literal way
Set oneWay = {};
// the constructor way
Set orAnother = <String>{};
Set petTypes = {'cat', 'dog', 'bird', 'reptile', 'other'};
print('There are ${petTypes.length} pet types defined.');
}

Type Symbol

Symbols represent an operator or identifier.

They can be created using the constructor Symbol('name') or the symbol literal #

Symbols are rarely used. They shine when building APIs that refer to identifiers by name, because minification changes identifier names but not identifier symbols.

Symbols created with the same name are equal:

void main() {
print(Symbol('a') == #a);
// the above prints true
}

Type Runes

Runes are UTF-32 code points of String. To express 32-bit Unicode values in a string, we can use the form \u****, were ****is the four-digit hexadecimal value of the code point.

If the code point is larger than 4, we'll use the {} to wrap the digits ( \u{*****}).

void main() {
Runes heart = Runes('\u2665');
Runes laugh = Runes('\u{1f600}');
print(String.fromCharCodes(heart) + ' ' + String.fromCharCodes(laugh));
}

The above prints: '♥ 😀'


Next to the above built-in types we have the enum and the dynamic types.

An enumerated type can be declared using the enum keyword, and allows us to define a set of constant values in a type-safe way (usually used in switch statements). Each value has an index getter to return the zero-based position of that value. values gives us access to all values in an enum.

enum Pet { cat, dog, bird, reptile, other }void main() {
print('${Pet.values.length} pet types');
dynamic myPet = Pet.cat;
switch(myPet) {
case Pet.cat:
print('meow');
break;
case Pet.dog:
print('woof');
break;
case Pet.bird:
print('tweet');
break;
case Pet.reptile:
print('ssSss');
break;
case Pet.other:
print('');
break;
}
}

The dynamic type is used when we don’t know (or care about) the type of an object.

The is operator can be used to check if the dynamic object is of some type (the runtimeType getter gives us access to the actual type).

Sometimes the dynamic type is confused with Object (which should be used when we want to indicate that all objects are accepted).

void main() {
dynamic value = false;
print(value.runtimeType);
value = 'Dart';
if(value is String) {
print(value.runtimeType);
}
}

All these built-in types are part of the Dart programming language and provide flexibility and options to type our objects.

Built-in data types of Dart

In the next article, from the Fluttering Dart series, I’ll continue exploring other Dart fundamentals needed for building Flutter apps.

Tha(nk|t’)s all!

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade