Language Tour Dart
Language Tour Dart
dev/guides/language/language-tour
To learn more about Dart’s core libraries, see the library tour. Whenever you want more details about a language feature, consult
the Dart language speci�cation.
Note: You can play with most of Dart’s language features using DartPad (learn more). Open DartPad.
This page uses embedded DartPads to display some of the examples. If you see empty boxes instead of DartPads, go to
the DartPad troubleshooting page.
∕∕ Define a function.
void printInteger(int aNumber) {
print('The number is $aNumber.'); ∕∕ Print to console.
}
Here’s what this program uses that applies to all (or almost all) Dart apps:
∕∕ This is a comment.
A single-line comment. Dart also supports multi-line and document comments. For details, see Comments.
void
A special type that indicates a value that’s never used. Functions like printInteger() and main() that don’t explicitly return a
value have the void return type.
int
Another type, indicating an integer. Some additional built-in types are String, List, and bool.
42
A number literal. Number literals are a kind of compile-time constant.
print()
A handy way to display output.
main()
The special, required, top-level function where app execution starts. For more information, see The main() function.
var
1 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
A way to declare a variable without specifying its type. The type of this variable (int) is determined by its initial value (42).
Note: This site’s code follows the conventions in the Dart style guide.
Impo�ant concepts
As you learn about the Dart language, keep these facts and concepts in mind:
• Everything you can place in a variable is an object, and every object is an instance of a class. Even numbers, functions, and
null are objects. With the exception of null (if you enable sound null safety), all objects inherit from the Object class.
Version note: Null safety was introduced in Dart 2.12. Using null safety requires a language version of at least
2.12.
• Although Dart is strongly typed, type annotations are optional because Dart can infer types. In the code above, number is
inferred to be of type int.
• If you enable null safety, variables can’t contain null unless you say they can. You can make a variable nullable by putting a
question mark (?) at the end of its type. For example, a variable of type int? might be an integer, or it might be null. If you
know that an expression never evaluates to null but Dart disagrees, you can add ! to assert that it isn’t null (and to throw
an exception if it is). An example: int x = nullableButNotNullInt!
• When you want to explicitly say that any type is allowed, use the type Object? (if you’ve enabled null safety), Object, or —
if you must defer type checking until runtime — the special type dynamic.
• Dart supports generic types, like List<int> (a list of integers) or List<Object> (a list of objects of any type).
• Dart supports top-level functions (such as main()), as well as functions tied to a class or object (static and instance
methods, respectively). You can also create functions within functions (nested or local functions).
• Similarly, Dart supports top-level variables, as well as variables tied to a class or object (static and instance variables).
Instance variables are sometimes known as �elds or properties.
• Unlike Java, Dart doesn’t have the keywords public, protected, and private. If an identi�er starts with an underscore
(_), it’s private to its library. For details, see Libraries and visibility.
• Identi�ers can start with a letter or underscore (_), followed by any combination of those characters plus digits.
• Dart has both expressions (which have runtime values) and statements (which don’t). For example, the conditional
expression condition ? expr1 : expr2 has a value of expr1 or expr2. Compare that to an if-else statement, which
has no value. A statement often contains one or more expressions, but an expression can’t directly contain a statement.
• Dart tools can report two kinds of problems: warnings and errors. Warnings are just indications that your code might not
work, but they don’t prevent your program from executing. Errors can be either compile-time or run-time. A compile-time
error prevents the code from executing at all; a run-time error results in an exception being raised while the code executes.
Keywords
The following table lists the words that the Dart language treats specially.
2 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
do if return yield 3
Avoid using these words as identi�ers. However, if necessary, the keywords marked with superscripts can be identi�ers:
• Words with the superscript 1 are contextual keywords, which have meaning only in speci�c places. They’re valid identi�ers
everywhere.
• Words with the superscript 2 are built-in identi�ers. These keywords are valid identi�ers in most places, but they can’t be
used as class or type names, or as import pre�xes.
• Words with the superscript 3 are limited reserved words related to asynchrony support. You can’t use await or yield as an
identi�er in any function body marked with async, async*, or sync*.
All other words in the table are reserved words, which can’t be identi�ers.
Variables
Here’s an example of creating a variable and initializing it:
Variables store references. The variable called name contains a reference to a String object with a value of “Bob”.
The type of the name variable is inferred to be String, but you can change that type by specifying it. If an object isn’t restricted to
a single type, specify the Object type (or dynamic if necessary).
Note: This page follows the style guide recommendation of using var, rather than type annotations, for local
variables.
3 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Default value
Uninitialized variables that have a nullable type have an initial value of null. (If you haven’t opted into null safety, then every
variable has a nullable type.) Even variables with numeric types are initially null, because numbers—like everything else in Dart—
are objects.
int? lineCount;
assert(lineCount == null);
Note: Production code ignores the assert() call. During development, on the other hand, assert(condition)
throws an exception if condition is false. For details, see Assert.
If you enable null safety, then you must initialize the values of non-nullable variables before you use them:
int lineCount = 0;
You don’t have to initialize a local variable where it’s declared, but you do need to assign it a value before it’s used. For example,
the following code is valid because Dart can detect that lineCount is non-null by the time it’s passed to print():
int lineCount;
if (weLikeToCount) {
lineCount = countLines();
} else {
lineCount = 0;
}
print(lineCount);
Top-level and class variables are lazily initialized; the initialization code runs the �rst time the variable is used.
Late variables
Dart 2.12 added the late modi�er, which has two use cases:
Often Dart’s control �ow analysis can detect when a non-nullable variable is set to a non-null value before it’s used, but sometimes
analysis fails. Two common cases are top-level variables and instance variables: Dart often can’t determine whether they’re set,
so it doesn’t try.
If you’re sure that a variable is set before it’s used, but Dart disagrees, you can �x the error by marking the variable as late:
void main() {
description = 'Feijoada!';
print(description);
}
If you fail to initialize a late variable, a runtime error occurs when the variable is used.
4 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
When you mark a variable as late but initialize it at its declaration, then the initializer runs the �rst time the variable is used. This
lazy initialization is handy in a couple of cases:
In the following example, if the temperature variable is never used, then the expensive _readThermometer() function is
never called:
Use const for variables that you want to be compile-time constants. If the const variable is at the class level, mark it static
const. Where you declare the variable, set the value to a compile-time constant such as a number or string literal, a const
variable, or the result of an arithmetic operation on constant numbers:
The const keyword isn’t just for declaring constant variables. You can also use it to create constant values, as well as to declare
constructors that create constant values. Any variable can have a constant value.
You can omit const from the initializing expression of a const declaration, like for baz above. For details, see DON’T use const
redundantly.
You can change the value of a non-�nal, non-const variable, even if it used to have a const value:
5 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
You can de�ne constants that use type checks and casts (is and as), collection if, and spread operators (... and ...?):
Note: Although a final object cannot be modi�ed, its �elds can be changed. In comparison, a const object and its
�elds cannot be changed: they’re immutable.
For more information on using const to create constant values, see Lists, Maps, and Classes.
Built-in types
The Dart language has special support for the following:
This support includes the ability to create objects using literals. For example, 'this is a string' is a string literal, and true
is a boolean literal.
Because every variable in Dart refers to an object—an instance of a class—you can usually use constructors to initialize variables.
Some of the built-in types have their own constructors. For example, you can use the Map() constructor to create a map.
Some other types also have special roles in the Dart language:
The Object, Object?, Null, and Never classes have special roles in the class hierarchy, as described in the top-and-bottom
section of Understanding null safety.
Numbers
Dart numbers come in two �avors:
int
Integer values no larger than 64 bits, depending on the platform. On native platforms, values can be from -263 to 263 - 1. On the
web, integer values are represented as JavaScript numbers (64-bit �oating-point values with no fractional part) and can be from
-253 to 253 - 1.
double
64-bit (double-precision) �oating-point numbers, as speci�ed by the IEEE 754 standard.
6 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Both int and double are subtypes of num. The num type includes basic operators such as +, -, /, and *, and is also where you’ll
�nd abs(), ceil(), and floor(), among other methods. (Bitwise operators, such as >>, are de�ned in the int class.) If num
and its subtypes don’t have what you’re looking for, the dart:math library might.
Integers are numbers without a decimal point. Here are some examples of de�ning integer literals:
var x = 1;
var hex = 0xDEADBEEF;
var exponent = 8e5;
If a number includes a decimal, it is a double. Here are some examples of de�ning double literals:
var y = 1.1;
var exponents = 1.42e5;
You can also declare a variable as a num. If you do this, the variable can have both integer and double values.
The int type speci�es the traditional bitwise shift (<<, >>, >>>), complement (~), AND (&), OR (|), and XOR (^) operators, which
are useful for manipulating and masking �ags in bit �elds. For example:
For more examples, see the bitwise and shift operator section.
Literal numbers are compile-time constants. Many arithmetic expressions are also compile-time constants, as long as their
operands are compile-time constants that evaluate to numbers.
7 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Strings
A Dart string (String object) holds a sequence of UTF-16 code units. You can use either single or double quotes to create a
string:
You can put the value of an expression inside a string by using ${expression}. If the expression is an identi�er, you can skip the
{}. To get the string corresponding to an object, Dart calls the object’s toString() method.
Note: The == operator tests whether two objects are equivalent. Two strings are equivalent if they contain the same
sequence of code units.
You can concatenate strings using adjacent string literals or the + operator:
Another way to create a multi-line string: use a triple quote with either single or double quotation marks:
var s1 = '''
You can create
multi-line strings like this one.
''';
8 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
See Runes and grapheme clusters for details on how to express Unicode characters in a string.
Literal strings are compile-time constants, as long as any interpolated expression is a compile-time constant that evaluates to null
or a numeric, string, or boolean value.
For more information on using strings, see Strings and regular expressions.
Booleans
To represent boolean values, Dart has a type named bool. Only two objects have type bool: the boolean literals true and false,
which are both compile-time constants.
Dart’s type safety means that you can’t use code like if (nonbooleanValue) or assert (nonbooleanValue). Instead,
explicitly check for values, like this:
Lists
Perhaps the most common collection in nearly every programming language is the array, or ordered group of objects. In Dart,
arrays are List objects, so most people just call them lists.
Dart list literals look like JavaScript array literals. Here’s a simple Dart list:
9 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Note: Dart infers that list has type List<int>. If you try to add non-integer objects to this list, the analyzer or
runtime raises an error. For more information, read about type inference.
You can add a comma after the last item in a Dart collection literal. This trailing comma doesn’t affect the collection, but it can
help prevent copy-paste errors.
var list = [
'Car',
'Boat',
'Plane',
];
Lists use zero-based indexing, where 0 is the index of the �rst value and list.length - 1 is the index of the last value. You
can get a list’s length and refer to list values just as you would in JavaScript:
list[1] = 1;
assert(list[1] == 1);
To create a list that’s a compile-time constant, add const before the list literal:
Dart 2.3 introduced the spread operator (...) and the null-aware spread operator (...?), which provide a concise way to insert
multiple values into a collection.
For example, you can use the spread operator (...) to insert all the values of a list into another list:
If the expression to the right of the spread operator might be null, you can avoid exceptions by using a null-aware spread operator
(...?):
var list;
var list2 = [0, ...?list];
assert(list2.length == 1);
For more details and examples of using the spread operator, see the spread operator proposal.
Dart also offers collection if and collection for, which you can use to build collections using conditionals (if) and repetition
(for).
Here’s an example of using collection if to create a list with three or four items in it:
10 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Here’s an example of using collection for to manipulate the items of a list before adding them to another list:
For more details and examples of using collection if and for, see the control �ow collections proposal.
The List type has many handy methods for manipulating lists. For more information about lists, see Generics and Collections.
Sets
A set in Dart is an unordered collection of unique items. Dart support for sets is provided by set literals and the Set type.
Note: Dart infers that halogens has the type Set<String>. If you try to add the wrong type of value to the set, the
analyzer or runtime raises an error. For more information, read about type inference.
To create an empty set, use {} preceded by a type argument, or assign {} to a variable of type Set:
Set or map? The syntax for map literals is similar to that for set literals. Because map literals came �rst, {} defaults to
the Map type. If you forget the type annotation on {} or the variable it’s assigned to, then Dart creates an object of type
Map<dynamic, dynamic>.
To create a set that’s a compile-time constant, add const before the set literal:
11 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Sets support spread operators (... and ...?) and collection if and for, just like lists do. For more information, see the list
spread operator and list collection operator discussions.
Maps
In general, a map is an object that associates keys and values. Both keys and values can be any type of object. Each key occurs
only once, but you can use the same value multiple times. Dart support for maps is provided by map literals and the Map type.
Here are a couple of simple Dart maps, created using map literals:
var gifts = {
∕∕ Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
var nobleGases = {
2: 'helium',
10: 'neon',
18: 'argon',
};
Note: Dart infers that gifts has the type Map<String, String> and nobleGases has the type Map<int,
String>. If you try to add the wrong type of value to either map, the analyzer or runtime raises an error. For more
information, read about type inference.
Note: If you come from a language like C# or Java, you might expect to see new Map() instead of just Map(). In Dart,
the new keyword is optional. For details, see Using constructors.
Add a new key-value pair to an existing map just as you would in JavaScript:
12 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Retrieve a value from a map the same way you would in JavaScript:
If you look for a key that isn’t in a map, you get a null in return:
To create a map that’s a compile-time constant, add const before the map literal:
Maps support spread operators (... and ...?) and collection if and for, just like lists do. For details and examples, see the
spread operator proposal and the control �ow collections proposal.
For more information about maps, see the generics section and the library tour’s coverage of the Maps API.
Unicode de�nes a unique numeric value for each letter, digit, and symbol used in all of the world’s writing systems. Because a Dart
string is a sequence of UTF-16 code units, expressing Unicode code points within a string requires special syntax. The usual way
to express a Unicode code point is \uXXXX, where XXXX is a 4-digit hexadecimal value. For example, the heart character (♥) is
\u2665. To specify more or less than 4 hex digits, place the value in curly brackets. For example, the laughing emoji (�
�) is
\u{1f606}.
If you need to read or write individual Unicode characters, use the characters getter de�ned on String by the characters
package. The returned Characters object is the string as a sequence of grapheme clusters. Here’s an example of using the
characters API:
13 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
import 'package:characters∕characters.dart';
...
var hi = 'Hi �';
print(hi);
print('The end of the string: ${hi.substring(hi.length - 1)}');
print('The last character: ${hi.characters.last}\n');
For details on using the characters package to manipulate strings, see the example and API reference for the characters package.
Symbols
A Symbol object represents an operator or identi�er declared in a Dart program. You might never need to use symbols, but they’re
invaluable for APIs that refer to identi�ers by name, because mini�cation changes identi�er names but not identi�er symbols.
To get the symbol for an identi�er, use a symbol literal, which is just # followed by the identi�er:
#radix
#bar
Functions
Dart is a true object-oriented language, so even functions are objects and have a type, Function. This means that functions can be
assigned to variables or passed as arguments to other functions. You can also call an instance of a Dart class as if it were a
function. For details, see Callable classes.
Although Effective Dart recommends type annotations for public APIs, the function still works if you omit the types:
isNoble(atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
For functions that contain just one expression, you can use a shorthand syntax:
The => expr syntax is a shorthand for { return expr; }. The => notation is sometimes referred to as arrow syntax.
14 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Note: Only an expression—not a statement—can appear between the arrow (=>) and the semicolon (;). For example,
you can’t put an if statement there, but you can use a conditional expression.
Parameters
A function can have any number of required positional parameters. These can be followed either by named parameters or by
optional positional parameters (but not both).
Note: Some APIs — notably Flutter widget constructors — use only named parameters, even for parameters that are
mandatory. See the next section for details.
You can use trailing commas when you pass arguments to a function or when you de�ne function parameters.
Named parameters
Named parameters are optional unless they’re speci�cally marked as required.
When calling a function, you can specify named parameters using paramName: value. For example:
Although named parameters are a kind of optional parameter, you can annotate them with required to indicate that the
parameter is mandatory — that users must provide a value for the parameter. For example:
If someone tries to create a Scrollbar without specifying the child argument, then the analyzer reports an issue.
15 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
And here’s an example of calling this function with the third parameter:
Deprecation note: Old code might use a colon (:) instead of = to set default values of named parameters. The reason
is that originally, only : was supported for named parameters. That support might be deprecated, so we recommend that
you use = to specify default values.
The next example shows how to set default values for positional parameters:
You can also pass lists or maps as default values. The following example de�nes a function, doStuff(), that speci�es a default
list for the list parameter and a default map for the gifts parameter.
void doStuff(
{List<int> list = const [1, 2, 3],
Map<String, String> gifts = const {
'first': 'paper',
'second': 'cotton',
'third': 'leather'
}}) {
print('list: $list');
print('gifts: $gifts');
}
16 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
void main() {
print('Hello, World!');
}
Here’s an example of the main() function for a command-line app that takes arguments:
assert(arguments.length == 2);
assert(int.parse(arguments[0]) == 1);
assert(arguments[1] == 'test');
}
You can use the args library to de�ne and parse command-line arguments.
This example uses an anonymous function. More about those in the next section.
Anonymous functions
Most functions are named, such as main() or printElement(). You can also create a nameless function called an anonymous
function, or sometimes a lambda or closure. You might assign an anonymous function to a variable so that, for example, you can
add or remove it from a collection.
An anonymous function looks similar to a named function— zero or more parameters, separated by commas and optional type
annotations, between parentheses.
The following example de�nes an anonymous function with an untyped parameter, item. The function, invoked for each item in
the list, prints a string that includes the value at the speci�ed index.
17 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Dar t
Install SDK Format Reset Run
xxxxxxxxxx Console
1
void main() {
list.forEach((item) {
4
info line 3 • Avoid using `forEach` with a function
print('${list.indexOf(item)}: $item'); literal. (view docs)
5
1 issue hide
});
If the function contains only a single expression or return statement, you can shorten it using arrow notation. Paste the following
line into DartPad and click Run to verify that it is functionally equivalent.
Lexical scope
Dart is a lexically scoped language, which means that the scope of variables is determined statically, simply by the layout of the
code. You can “follow the curly braces outwards” to see if a variable is in scope.
void main() {
var insideMain = true;
void myFunction() {
var insideFunction = true;
void nestedFunction() {
var insideNestedFunction = true;
assert(topLevel);
assert(insideMain);
assert(insideFunction);
assert(insideNestedFunction);
}
}
}
Notice how nestedFunction() can use variables from every level, all the way up to the top level.
Lexical closures
18 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
A closure is a function object that has access to variables in its lexical scope, even when the function is used outside of its
original scope.
Functions can close over variables de�ned in surrounding scopes. In the following example, makeAdder() captures the variable
addBy. Wherever the returned function goes, it remembers addBy.
void main() {
∕∕ Create a function that adds 2.
var add2 = makeAdder(2);
assert(add2(3) == 5);
assert(add4(3) == 7);
}
class A {
static void bar() {} ∕∕ A static method
void baz() {} ∕∕ An instance method
}
void main() {
Function x;
Return values
All functions return a value. If no return value is speci�ed, the statement return null; is implicitly appended to the function
body.
19 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
foo() {}
assert(foo() == null);
Operators
Dart supports the operators shown in the following table. You can implement many of these operators as class members.
Description Operator
unary pre�x -expr !expr ~expr ++expr --expr await expr
multiplicative * ∕ % ~∕
additive + -
bitwise XOR ^
bitwise OR |
equality == !=
logical OR ||
if null ??
cascade .. ?..
Warning: Operator precedence is an approximation of the behavior of a Dart parser. For de�nitive answers, consult the
grammar in the Dart language speci�cation.
When you use operators, you create expressions. Here are some examples of operator expressions:
a++
a + b
a = b
a == b
c ? a : b
a is T
In the operator table, each operator has higher precedence than the operators in the rows that follow it. For example, the
20 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
multiplicative operator % has higher precedence than (and thus executes before) the equality operator ==, which has higher
precedence than the logical AND operator &&. That precedence means that the following two lines of code execute the same way:
Warning: For operators that take two operands, the leftmost operand determines which method is used. For example,
if you have a Vector object and a Point object, then aVector + aPoint uses Vector addition (+).
Arithmetic operators
Dart supports the usual arithmetic operators, as shown in the following table.
Operator Meaning
+ Add
– Subtract
-expr Unary minus, also known as negation (reverse the sign of the expression)
* Multiply
∕ Divide
Example:
assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 ∕ 2 == 2.5); ∕∕ Result is a double
assert(5 ~∕ 2 == 2); ∕∕ Result is an int
assert(5 % 2 == 1); ∕∕ Remainder
Dart also supports both pre�x and post�x increment and decrement operators.
Operator Meaning
Example:
21 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
int a;
int b;
a = 0;
b = ++a; ∕∕ Increment a before b gets its value.
assert(a == b); ∕∕ 1 == 1
a = 0;
b = a++; ∕∕ Increment a AFTER b gets its value.
assert(a != b); ∕∕ 1 != 0
a = 0;
b = --a; ∕∕ Decrement a before b gets its value.
assert(a == b); ∕∕ -1 == -1
a = 0;
b = a--; ∕∕ Decrement a AFTER b gets its value.
assert(a != b); ∕∕ -1 != 0
Operator Meaning
!= Not equal
To test whether two objects x and y represent the same thing, use the == operator. (In the rare case where you need to know
whether two objects are the exact same object, use the identical() function instead.) Here’s how the == operator works:
1. If x or y is null, return true if both are null, and false if only one is null.
2. Return the result of invoking the == method on x with the argument y. (That’s right, operators such as == are methods that
are invoked on their �rst operand. For details, see Operators.)
assert(2 == 2);
assert(2 != 3);
assert(3 > 2);
assert(2 < 3);
assert(3 >= 3);
assert(2 <= 3);
Operator Meaning
22 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Operator Meaning
The result of obj is T is true if obj implements the interface speci�ed by T. For example, obj is Object? is always true.
Use the as operator to cast an object to a particular type if and only if you are sure that the object is of that type. Example:
If you aren’t sure that the object is of type T, then use is T to check the type before using the object.
if (employee is Person) {
∕∕ Type check
employee.firstName = 'Bob';
}
Note: The code isn’t equivalent. If employee is null or not a Person, the �rst example throws an exception; the
second does nothing.
Assignment operators
As you’ve already seen, you can assign values using the = operator. To assign only if the assigned-to variable is null, use the ??=
operator.
∕∕ Assign value to a
a = value;
∕∕ Assign value to b if b is null; otherwise, b stays the same
b ??= value;
= *= %= >>>= ^=
+= ∕= <<= &= |=
-= ~∕= >>=
Example: a += b a = a + b
23 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Logical operators
You can invert or combine boolean expressions using the logical operators.
Operator Meaning
!expr inverts the following expression (changes false to true, and vice versa)
|| logical OR
Operator Meaning
& AND
| OR
^ XOR
24 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Version note: The >>> operator (known as triple-shift or unsigned shift) requires a language version of at least 2.14.
Conditional expressions
Dart has two operators that let you concisely evaluate expressions that might otherwise require if-else statements:
condition ? expr1 : expr2
If condition is true, evaluates expr1 (and returns its value); otherwise, evaluates and returns the value of expr2.
expr1 ?? expr2
If expr1 is non-null, returns its value; otherwise, evaluates and returns the value of expr2.
When you need to assign a value based on a boolean expression, consider using ? and :.
The previous example could have been written at least two other ways, but not as succinctly:
Cascade notation
Cascades (.., ?..) allow you to make a sequence of operations on the same object. In addition to function calls, you can also
access �elds on that same object. This often saves you the step of creating a temporary variable and allows you to write more
�uid code.
The constructor, Paint(), returns a Paint object. The code that follows the cascade notation operates on this object, ignoring
any values that might be returned.
25 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
If the object that the cascade operates on can be null, then use a null-shorting cascade (?..) for the �rst operation. Starting with
?.. guarantees that none of the cascade operations are attempted on that null object.
Version note: The ?.. syntax requires a language version of at least 2.12.
Be careful to construct your cascade on a function that returns an actual object. For example, the following code fails:
var sb = StringBuffer();
sb.write('foo')
..write('bar'); ∕∕ Error: method 'write' isn't defined for 'void'.
The sb.write() call returns void, and you can’t construct a cascade on void.
Note: Strictly speaking, the “double dot” notation for cascades isn’t an operator. It’s just part of the Dart syntax.
Other operators
You’ve seen most of the remaining operators in other examples:
26 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
[] Subscript access Represents a call to the overridable [] operator; example: fooList[1] passes the int 1 to
fooList to access the element at index 1
?[] Conditional Like [], but the leftmost operand can be null; example: fooList?[1] passes the int 1 to
subscript access fooList to access the element at index 1 unless fooList is null (in which case the
expression evaluates to null)
. Member access Refers to a property of an expression; example: foo.bar selects property bar from
expression foo
?. Conditional Like ., but the leftmost operand can be null; example: foo?.bar selects property bar from
member access expression foo unless foo is null (in which case the value of foo?.bar is null)
For more information about the ., ?., and .. operators, see Classes.
• if and else
• for loops
• while and do-while loops
• break and continue
• switch and case
• assert
You can also affect the control �ow using try-catch and throw, as explained in Exceptions.
If and else
Dart supports if statements with optional else statements, as the next sample shows. Also see conditional expressions.
if (isRaining()) {
you.bringRainCoat();
} else if (isSnowing()) {
you.wearJacket();
} else {
car.putTopDown();
}
Unlike JavaScript, conditions must use boolean values, nothing else. See Booleans for more information.
For loops
You can iterate with the standard for loop. For example:
Closures inside of Dart’s for loops capture the value of the index, avoiding a common pitfall found in JavaScript. For example,
consider:
27 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
The output is 0 and then 1, as expected. In contrast, the example would print 2 and then 2 in JavaScript.
If the object that you are iterating over is an Iterable (such as List or Set) and if you don’t need to know the current iteration
counter, you can use the for-in form of iteration:
while (!isDone()) {
doSomething();
}
do {
printLine();
} while (!atEndOfPage());
while (true) {
if (shutDownRequested()) break;
processIncomingRequests();
}
28 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
You might write that example differently if you’re using an Iterable such as a list or set:
candidates
.where((c) => c.yearsExperience >= 5)
.forEach((c) => c.interview());
Each non-empty case clause ends with a break statement, as a rule. Other valid ways to end a non-empty case clause are a
continue, throw, or return statement.
The following example omits the break statement in a case clause, thus generating an error:
case 'CLOSED':
executeClosed();
break;
}
29 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
However, Dart does support empty case clauses, allowing a form of fall-through:
If you really want fall-through, you can use a continue statement and a label:
nowClosed:
case 'NOW_CLOSED':
∕∕ Runs for both CLOSED and NOW_CLOSED.
executeNowClosed();
break;
}
A case clause can have local variables, which are visible only inside the scope of that clause.
Asse�
During development, use an assert statement — assert(condition, optionalMessage); — to disrupt normal execution if a
boolean condition is false. You can �nd examples of assert statements throughout this tour. Here are some more:
To attach a message to an assertion, add a string as the second argument to assert (optionally with a trailing comma):
assert(urlString.startsWith('https'),
'URL ($urlString) should start with "https".');
The �rst argument to assert can be any expression that resolves to a boolean value. If the expression’s value is true, the
assertion succeeds and execution continues. If it’s false, the assertion fails and an exception (an AssertionError) is thrown.
When exactly do assertions work? That depends on the tools and framework you’re using:
In production code, assertions are ignored, and the arguments to assert aren’t evaluated.
30 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Exceptions
Your Dart code can throw and catch exceptions. Exceptions are errors indicating that something unexpected happened. If the
exception isn’t caught, the isolate that raised the exception is suspended, and typically the isolate and its program are terminated.
In contrast to Java, all of Dart’s exceptions are unchecked exceptions. Methods don’t declare which exceptions they might throw,
and you aren’t required to catch any exceptions.
Dart provides Exception and Error types, as well as numerous prede�ned subtypes. You can, of course, de�ne your own
exceptions. However, Dart programs can throw any non-null object—not just Exception and Error objects—as an exception.
Throw
Here’s an example of throwing, or raising, an exception:
Note: Production-quality code usually throws types that implement Error or Exception.
Because throwing an exception is an expression, you can throw exceptions in => statements, as well as anywhere else that allows
expressions:
Catch
Catching, or capturing, an exception stops the exception from propagating (unless you rethrow the exception). Catching an
exception gives you a chance to handle it:
try {
breedMoreLlamas();
} on OutOfLlamasException {
buyMoreLlamas();
}
To handle code that can throw more than one type of exception, you can specify multiple catch clauses. The �rst catch clause
that matches the thrown object’s type handles the exception. If the catch clause does not specify a type, that clause can handle
any type of thrown object:
31 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
try {
breedMoreLlamas();
} on OutOfLlamasException {
∕∕ A specific exception
buyMoreLlamas();
} on Exception catch (e) {
∕∕ Anything else that is an exception
print('Unknown exception: $e');
} catch (e) {
∕∕ No specified type, handles all
print('Something really unknown: $e');
}
As the preceding code shows, you can use either on or catch or both. Use on when you need to specify the exception type. Use
catch when your exception handler needs the exception object.
You can specify one or two parameters to catch(). The �rst is the exception that was thrown, and the second is the stack trace
(a StackTrace object).
try {
∕∕ ···
} on Exception catch (e) {
print('Exception details:\n $e');
} catch (e, s) {
print('Exception details:\n $e');
print('Stack trace:\n $s');
}
To partially handle an exception, while allowing it to propagate, use the rethrow keyword.
void misbehave() {
try {
dynamic foo = true;
print(foo++); ∕∕ Runtime error
} catch (e) {
print('misbehave() partially handled ${e.runtimeType}.');
rethrow; ∕∕ Allow callers to see the exception.
}
}
void main() {
try {
misbehave();
} catch (e) {
print('main() finished handling ${e.runtimeType}.');
}
}
Finally
To ensure that some code runs whether or not an exception is thrown, use a finally clause. If no catch clause matches the
exception, the exception is propagated after the finally clause runs:
try {
breedMoreLlamas();
} finally {
∕∕ Always clean up, even if an exception is thrown.
cleanLlamaStalls();
}
32 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
try {
breedMoreLlamas();
} catch (e) {
print('Error: $e'); ∕∕ Handle the exception first.
} finally {
cleanLlamaStalls(); ∕∕ Then clean up.
}
Classes
Dart is an object-oriented language with classes and mixin-based inheritance. Every object is an instance of a class, and all
classes except Null descend from Object. Mixin-based inheritance means that although every class (except for the top class,
Object?) has exactly one superclass, a class body can be reused in multiple class hierarchies. Extension methods are a way to
add functionality to a class without changing the class or creating a subclass.
∕∕ Invoke distanceTo() on p.
double distance = p.distanceTo(Point(4, 4));
Using constructors
You can create an object using a constructor. Constructor names can be either ClassName or ClassName.identifier. For
example, the following code creates Point objects using the Point() and Point.fromJson() constructors:
The following code has the same effect, but uses the optional new keyword before the constructor name:
Some classes provide constant constructors. To create a compile-time constant using a constant constructor, put the const
keyword before the constructor name:
33 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Within a constant context, you can omit the const before a constructor or literal. For example, look at this code, which creates a
const map:
You can omit all but the �rst use of the const keyword:
If a constant constructor is outside of a constant context and is invoked without const, it creates a non-constant object:
Use a type test operator rather than runtimeType to test an object’s type. In production environments, the test
object is Type is more stable than the test object.runtimeType == Type.
Up to here, you’ve seen how to use classes. The rest of this section shows how to implement classes.
Instance variables
Here’s how you declare instance variables:
34 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
class Point {
double? x; ∕∕ Declare instance variable x, initially null.
double? y; ∕∕ Declare y, initially null.
double z = 0; ∕∕ Declare z, initially 0.
}
All instance variables generate an implicit getter method. Non-�nal instance variables and late final instance variables
without initializers also generate an implicit setter method. For details, see Getters and setters.
If you initialize a non-late instance variable where it’s declared, the value is set when the instance is created, which is before the
constructor and its initializer list execute.
class Point {
double? x; ∕∕ Declare instance variable x, initially null.
double? y; ∕∕ Declare y, initially null.
}
void main() {
var point = Point();
point.x = 4; ∕∕ Use the setter method for x.
assert(point.x == 4); ∕∕ Use the getter method for x.
assert(point.y == null); ∕∕ Values default to null.
}
Instance variables can be final, in which case they must be set exactly once. Initialize final, non-late instance variables at
declaration, using a constructor parameter, or using a constructor’s initializer list:
class ProfileMark {
final String name;
final DateTime start = DateTime.now();
ProfileMark(this.name);
ProfileMark.unnamed() : name = '';
}
If you need to assign the value of a final instance variable after the constructor body starts, you can use one of the following:
Constructors
Declare a constructor by creating a function with the same name as its class (plus, optionally, an additional identi�er as described
in Named constructors). The most common form of constructor, the generative constructor, creates a new instance of a class:
class Point {
double x = 0;
double y = 0;
Point(double x, double y) {
∕∕ There's a better way to do this, stay tuned.
this.x = x;
this.y = y;
}
}
35 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Note: Use this only when there is a name con�ict. Otherwise, Dart style omits the this.
The pattern of assigning a constructor argument to an instance variable is so common, Dart has syntactic sugar to make it easy:
class Point {
double x = 0;
double y = 0;
Default constructors
If you don’t declare a constructor, a default constructor is provided for you. The default constructor has no arguments and invokes
the no-argument constructor in the superclass.
Named constructors
Use a named constructor to implement multiple constructors for a class or to provide extra clarity:
class Point {
double x = 0;
double y = 0;
Point(this.x, this.y);
∕∕ Named constructor
Point.origin()
: x = xOrigin,
y = yOrigin;
}
Remember that constructors are not inherited, which means that a superclass’s named constructor is not inherited by a subclass.
If you want a subclass to be created with a named constructor de�ned in the superclass, you must implement that constructor in
the subclass.
1. initializer list
2. superclass’s no-arg constructor
3. main class’s no-arg constructor
If the superclass doesn’t have an unnamed, no-argument constructor, then you must manually call one of the constructors in the
superclass. Specify the superclass constructor after a colon (:), just before the constructor body (if any).
In the following example, the constructor for the Employee class calls the named constructor for its superclass, Person. Click Run
to execute the code.
36 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Dar t
Install SDK Format Reset Run
Console
xxxxxxxxxx
no issues
Because the arguments to the superclass constructor are evaluated before invoking the constructor, an argument can be an
expression such as a function call:
Warning: Arguments to the superclass constructor don’t have access to this. For example, arguments can call static
methods but not instance methods.
Initializer list
Besides invoking a superclass constructor, you can also initialize instance variables before the constructor body runs. Separate
initializers with commas.
During development, you can validate inputs by using assert in the initializer list.
Initializer lists are handy when setting up �nal �elds. The following example initializes three �nal �elds in an initializer list. Click
37 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Dar t
Install SDK Format Reset Run
Console
xxxxxxxxxx
1
import 'dart:math';
5
2 issues hide
final double y;
Redirecting constructors
Sometimes a constructor’s only purpose is to redirect to another constructor in the same class. A redirecting constructor’s body is
empty, with the constructor call (using this instead of the class name) appearing after a colon (:).
class Point {
double x, y;
Constant constructors
If your class produces objects that never change, you can make these objects compile-time constants. To do this, de�ne a const
constructor and make sure that all instance variables are final.
class ImmutablePoint {
static const ImmutablePoint origin = ImmutablePoint(0, 0);
final double x, y;
Constant constructors don’t always create constants. For details, see the section on using constructors.
Factory constructors
Use the factory keyword when implementing a constructor that doesn’t always create a new instance of its class. For example,
a factory constructor might return an instance from a cache, or it might return an instance of a subtype. Another use case for
factory constructors is initializing a �nal variable using logic that can’t be handled in the initializer list.
Tip: Another way to handle late initialization of a �nal variable is to use late final (carefully!).
In the following example, the Logger factory constructor returns objects from a cache, and the Logger.fromJson factory
38 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
class Logger {
final String name;
bool mute = false;
Logger._internal(this.name);
Invoke a factory constructor just like you would any other constructor:
Methods
Methods are functions that provide behavior for an object.
Instance methods
Instance methods on objects can access instance variables and this. The distanceTo() method in the following sample is an
example of an instance method:
import 'dart:math';
class Point {
double x = 0;
double y = 0;
Point(this.x, this.y);
39 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Operators
Operators are instance methods with special names. Dart allows you to de�ne operators with the following names:
< + | >>>
> ∕ ^ []
>= * << ~
– % >> ==
Note: You may have noticed that some operators, like !=, aren’t in the list of names. That’s because they’re just
syntactic sugar. For example, the expression e1 != e2 is syntactic sugar for !(e1 == e2).
An operator declaration is identi�ed using the built-in identi�er operator. The following example de�nes vector addition (+) and
subtraction (-):
class Vector {
final int x, y;
Vector(this.x, this.y);
void main() {
final v = Vector(2, 3);
final w = Vector(2, 2);
40 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
class Rectangle {
double left, top, width, height;
void main() {
var rect = Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12;
assert(rect.left == -8);
}
With getters and setters, you can start with instance variables, later wrapping them with methods, all without changing client
code.
Note: Operators such as increment (++) work in the expected way, whether or not a getter is explicitly de�ned. To avoid
any unexpected side effects, the operator calls the getter exactly once, saving its value in a temporary variable.
Abstract methods
Instance, getter, and setter methods can be abstract, de�ning an interface but leaving its implementation up to other classes.
Abstract methods can only exist in abstract classes.
Abstract classes
Use the abstract modi�er to de�ne an abstract class—a class that can’t be instantiated. Abstract classes are useful for de�ning
interfaces, often with some implementation. If you want your abstract class to appear to be instantiable, de�ne a factory
constructor.
Abstract classes often have abstract methods. Here’s an example of declaring an abstract class that has an abstract method:
41 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Implicit inte�aces
Every class implicitly de�nes an interface containing all the instance members of the class and of any interfaces it implements. If
you want to create a class A that supports class B’s API without inheriting B’s implementation, class A should implement the B
interface.
A class implements one or more interfaces by declaring them in an implements clause and then providing the APIs required by
the interfaces. For example:
∕∕ In the interface.
String greet(String who) => 'Hello, $who. I am $_name.';
}
String greet(String who) => 'Hi $who. Do you know who I am?';
}
void main() {
print(greetBob(Person('Kathy')));
print(greetBob(Impostor()));
}
Extending a class
Use extends to create a subclass, and super to refer to the superclass:
42 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
class Television {
void turnOn() {
_illuminateDisplay();
_activateIrSensor();
}
∕∕ ···
}
For another usage of extends, see the discussion of parameterized types in generics.
Overriding members
Subclasses can override instance methods (including operators), getters, and setters. You can use the @override annotation to
indicate that you are intentionally overriding a member:
class Television {
∕∕ ···
set contrast(int value) {...}
}
An overriding method declaration must match the method (or methods) that it overrides in several ways:
• The return type must be the same type as (or a subtype of) the overridden method’s return type.
• Argument types must be the same type as (or a supertype of) the overridden method’s argument types. In the preceding
example, the contrast setter of SmartTelevision changes the argument type from int to a supertype, num.
• If the overridden method accepts n positional parameters, then the overriding method must also accept n positional
parameters.
• A generic method can’t override a non-generic one, and a non-generic method can’t override a generic one.
Sometimes you might want to narrow the type of a method parameter or an instance variable. This violates the normal rules, and
it’s similar to a downcast in that it can cause a type error at runtime. Still, narrowing the type is possible if the code can guarantee
that a type error won’t occur. In this case, you can use the covariant keyword in a parameter declaration. For details, see the
Dart language speci�cation.
Warning: If you override ==, you should also override Object’s hashCode getter. For an example of overriding == and
hashCode, see Implementing map keys.
noSuchMethod()
To detect or react whenever code attempts to use a non-existent method or instance variable, you can override
noSuchMethod():
43 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
class A {
∕∕ Unless you override noSuchMethod, using a
∕∕ non-existent member results in a NoSuchMethodError.
@override
void noSuchMethod (Invocation invocation) {
print('You tried to use a non-existent member: '
'${invocation.memberName}');
}
}
You can’t invoke an unimplemented method unless one of the following is true:
• The receiver has a static type that de�nes the unimplemented method (abstract is OK), and the dynamic type of the receiver
has an implementation of noSuchMethod() that’s different from the one in class Object.
Extension methods
Extension methods are a way to add functionality to existing libraries. You might use extension methods without even knowing it.
For example, when you use code completion in an IDE, it suggests extension methods alongside regular methods.
Here’s an example of using an extension method on String named parseInt() that’s de�ned in string_apis.dart:
import 'string_apis.dart';
...
print('42'.padLeft(5)); ∕∕ Use a String method.
print('42'.parseInt()); ∕∕ Use an extension method.
For details of using and implementing extension methods, see the extension methods page.
Enumerated types
Enumerated types, often called enumerations or enums, are a special kind of class used to represent a �xed number of constant
values.
Using enums
Declare an enumerated type using the enum keyword:
Each value in an enum has an index getter, which returns the zero-based position of the value in the enum declaration. For
example, the �rst value has index 0, and the second value has index 1.
assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);
To get a list of all of the values in the enum, use the enum’s values constant.
44 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
You can use enums in switch statements, and you’ll get a warning if you don’t handle all of the enum’s values:
switch (aColor) {
case Color.red:
print('Red as roses!');
break;
case Color.green:
print('Green as grass!');
break;
default: ∕∕ Without this, you see a WARNING.
print(aColor); ∕∕ 'Color.blue'
}
To use a mixin, use the with keyword followed by one or more mixin names. The following example shows two classes that use
mixins:
To implement a mixin, create a class that extends Object and declares no constructors. Unless you want your mixin to be usable
as a regular class, use the mixin keyword instead of class. For example:
mixin Musical {
bool canPlayPiano = false;
bool canCompose = false;
bool canConduct = false;
void entertainMe() {
if (canPlayPiano) {
print('Playing piano');
} else if (canConduct) {
print('Waving hands');
} else {
print('Humming to self');
}
}
}
Sometimes you might want to restrict the types that can use a mixin. For example, the mixin might depend on being able to invoke
a method that the mixin doesn’t de�ne. As the following example shows, you can restrict a mixin’s use by using the on keyword to
specify the required superclass:
45 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
class Musician {
∕∕ ...
}
mixin MusicalPerformer on Musician {
∕∕ ...
}
class SingerDancer extends Musician with MusicalPerformer {
∕∕ ...
}
In the preceding code, only classes that extend or implement the Musician class can use the mixin MusicalPerformer.
Because SingerDancer extends Musician, SingerDancer can mix in MusicalPerformer.
Static variables
Static variables (class variables) are useful for class-wide state and constants:
class Queue {
static const initialCapacity = 16;
∕∕ ···
}
void main() {
assert(Queue.initialCapacity == 16);
}
Note: This page follows the style guide recommendation of preferring lowerCamelCase for constant names.
Static methods
Static methods (class methods) don’t operate on an instance, and thus don’t have access to this. They do, however, have access
to static variables. As the following example shows, you invoke static methods directly on a class:
import 'dart:math';
class Point {
double x, y;
Point(this.x, this.y);
void main() {
var a = Point(2, 2);
var b = Point(4, 4);
var distance = Point.distanceBetween(a, b);
assert(2.8 < distance && distance < 2.9);
print(distance);
}
46 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Note: Consider using top-level functions, instead of static methods, for common or widely used utilities and
functionality.
You can use static methods as compile-time constants. For example, you can pass a static method as a parameter to a constant
constructor.
Generics
If you look at the API documentation for the basic array type, List, you’ll see that the type is actually List<E>. The <…> notation
marks List as a generic (or parameterized) type—a type that has formal type parameters. By convention, most type variables have
single-letter names, such as E, T, S, K, and V.
If you intend for a list to contain only strings, you can declare it as List<String> (read that as “list of string”). That way you,
your fellow programmers, and your tools can detect that assigning a non-string to the list is probably a mistake. Here’s an
example:
Another reason for using generics is to reduce code duplication. Generics let you share a single interface and implementation
between many types, while still taking advantage of static analysis. For example, say you create an interface for caching an
object:
You discover that you want a string-speci�c version of this interface, so you create another interface:
Later, you decide you want a number-speci�c version of this interface… You get the idea.
Generic types can save you the trouble of creating all these interfaces. Instead, you can create a single interface that takes a type
parameter:
In this code, T is the stand-in type. It’s a placeholder that you can think of as a type that a developer will de�ne later.
47 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
The following code creates a map that has integer keys and values of type View:
Note: In contrast, generics in Java use erasure, which means that generic type parameters are removed at runtime. In
Java, you can test whether an object is a List, but you can’t test whether it’s a List<String>.
A common use case is ensuring that a type is non-nullable by making it a subtype of Object (instead of the default, Object?).
You can use extends with other types besides Object. Here’s an example of extending SomeBaseClass, so that members of
SomeBaseClass can be called on objects of type T:
48 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Here the generic type parameter on first (<T>) allows you to use the type argument T in several places:
If you’re curious why Dart uses underscores instead of access modi�er keywords like public or private, see SDK
issue 33383.
Using libraries
49 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Use import to specify how a namespace from one library is used in the scope of another library.
For example, Dart web apps generally use the dart:html library, which they can import like this:
import 'dart:html';
The only required argument to import is a URI specifying the library. For built-in libraries, the URI has the special dart: scheme.
For other libraries, you can use a �le system path or the package: scheme. The package: scheme speci�es libraries provided
by a package manager such as the pub tool. For example:
import 'package:test∕test.dart';
Note: URI stands for uniform resource identi�er. URLs (uniform resource locators) are a common kind of URI.
import 'package:lib1∕lib1.dart';
import 'package:lib2∕lib2.dart' as lib2;
Only dart2js supports deferred loading. Flutter, the Dart VM, and dartdevc don’t support deferred loading. For more
information, see issue #33118 and issue #27776.
To lazily load a library, you must �rst import it using deferred as.
50 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
When you need the library, invoke loadLibrary() using the library’s identi�er.
In the preceding code, the await keyword pauses execution until the library is loaded. For more information about async and
await, see asynchrony support.
You can invoke loadLibrary() multiple times on a library without problems. The library is loaded only once.
• A deferred library’s constants aren’t constants in the importing �le. Remember, these constants don’t exist until the deferred
library is loaded.
• You can’t use types from a deferred library in the importing �le. Instead, consider moving interface types to a library
imported by both the deferred library and the importing �le.
• Dart implicitly inserts loadLibrary() into the namespace that you de�ne using deferred as namespace. The
loadLibrary() function returns a Future.
Implementing libraries
See Create Library Packages for advice on how to implement a library package, including:
Asynchrony suppo�
Dart libraries are full of functions that return Future or Stream objects. These functions are asynchronous: they return after
setting up a possibly time-consuming operation (such as I/O), without waiting for that operation to complete.
The async and await keywords support asynchronous programming, letting you write asynchronous code that looks similar to
synchronous code.
Handling Futures
When you need the result of a completed Future, you have two options:
• Use async and await, as described here and in the asynchronous programming codelab.
• Use the Future API, as described in the library tour.
Code that uses async and await is asynchronous, but it looks a lot like synchronous code. For example, here’s some code that
uses await to wait for the result of an asynchronous function:
await lookUpVersion();
51 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
Note: Although an async function might perform time-consuming operations, it doesn’t wait for those operations.
Instead, the async function executes only until it encounters its �rst await expression (details). Then it returns a Future
object, resuming execution only after the await expression completes.
Use try, catch, and finally to handle errors and cleanup in code that uses await:
try {
version = await lookUpVersion();
} catch (e) {
∕∕ React to inability to look up the version
}
You can use await multiple times in an async function. For example, the following code waits three times for the results of
functions:
In await expression, the value of expression is usually a Future; if it isn’t, then the value is automatically wrapped in a
Future. This Future object indicates a promise to return an object. The value of await expression is that returned object. The
await expression makes execution pause until that object is available.
If you get a compile-time error when using await, make sure await is in an async function. For example, to use await in your
app’s main() function, the body of main() must be marked as async:
Note: The preceding example uses an async function (checkVersion()) without waiting for a result — a practice
that can cause problems if the code assumes that the function has �nished executing. To avoid this problem, use the
unawaited_futures linter rule.
For an interactive introduction to using futures, async, and await, see the asynchronous programming codelab.
Adding the async keyword to a function makes it return a Future. For example, consider this synchronous function, which returns
a String:
52 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
If you change it to be an async function—for example, because a future implementation will be time consuming—the returned
value is a Future:
Note that the function’s body doesn’t need to use the Future API. Dart creates the Future object if necessary. If your function
doesn’t return a useful value, make its return type Future<void>.
For an interactive introduction to using futures, async, and await, see the asynchronous programming codelab.
Handling Streams
When you need to get values from a Stream, you have two options:
Note: Before using await for, be sure that it makes the code clearer and that you really do want to wait for all of the
stream’s results. For example, you usually should not use await for for UI event listeners, because UI frameworks send
endless streams of events.
The value of expression must have type Stream. Execution proceeds as follows:
To stop listening to the stream, you can use a break or return statement, which breaks out of the for loop and unsubscribes
from the stream.
If you get a compile-time error when implementing an asynchronous for loop, make sure the await for is in an async
function. For example, to use an asynchronous for loop in your app’s main() function, the body of main() must be marked as
async:
For more information about asynchronous programming, in general, see the dart:async section of the library tour.
Generators
When you need to lazily produce a sequence of values, consider using a generator function. Dart has built-in support for two kinds
53 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
of generator functions:
To implement a synchronous generator function, mark the function body as sync*, and use yield statements to deliver values:
To implement an asynchronous generator function, mark the function body as async*, and use yield statements to deliver
values:
If your generator is recursive, you can improve its performance by using yield*:
Callable classes
To allow an instance of your Dart class to be called like a function, implement the call() method.
In the following example, the WannabeFunction class de�nes a call() function that takes three strings and concatenates them,
separating each with a space, and appending an exclamation. Click Run to execute the code.
Dar t
Install SDK Format Reset Run
Console
xxxxxxxxxx
1
class WannabeFunction {
5
no issues
var wf = WannabeFunction();
Isolates
Most computers, even on mobile platforms, have multi-core CPUs. To take advantage of all those cores, developers traditionally
use shared-memory threads running concurrently. However, shared-state concurrency is error prone and can lead to complicated
54 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
code.
Instead of threads, all Dart code runs inside of isolates. Each Dart isolate has a single thread of execution and shares no mutable
objects with other isolates.
• Concurrency in Dart
• dart:isolate API reference, including Isolate.spawn() and TransferableTypedData
• Background parsing cookbook on the Flutter site
• Isolate sample app
Typedefs
A type alias — often called a typedef because it’s declared with the keyword typedef — is a concise way to refer to a type. Here’s
an example of declaring and using a type alias named IntList:
Version note: Before 2.13, typedefs were restricted to function types. Using the new typedefs requires a language
version of at least 2.13.
We recommend using inline function types instead of typedefs for functions, in most situations. However, function typedefs can
still be useful:
void main() {
assert(sort is Compare<int>); ∕∕ True!
}
Metadata
Use metadata to give additional information about your code. A metadata annotation begins with the character @, followed by
either a reference to a compile-time constant (such as deprecated) or a call to a constant constructor.
Three annotations are available to all Dart code: @Deprecated, @deprecated, and @override. For examples of using
@override, see Extending a class. Here’s an example of using the @Deprecated annotation:
55 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
class Television {
∕∕∕ Use [turnOn] to turn the power on instead.
@Deprecated('Use turnOn instead')
void activate() {
turnOn();
}
You can de�ne your own metadata annotations. Here’s an example of de�ning a @Todo annotation that takes two arguments:
library todo;
class Todo {
final String who;
final String what;
import 'todo.dart';
Metadata can appear before a library, class, typedef, type parameter, constructor, factory, function, �eld, parameter, or variable
declaration and before an import or export directive. You can retrieve metadata at runtime using re�ection.
Comments
Dart supports single-line comments, multi-line comments, and documentation comments.
Single-line comments
A single-line comment begins with ∕∕. Everything between ∕∕ and the end of line is ignored by the Dart compiler.
void main() {
∕∕ TODO: refactor into an AbstractLlamaGreetingFactory?
print('Welcome to my Llama farm!');
}
Multi-line comments
A multi-line comment begins with ∕* and ends with *∕. Everything between ∕* and *∕ is ignored by the Dart compiler (unless the
comment is a documentation comment; see the next section). Multi-line comments can nest.
56 of 57 2/20/2022, 7:44 PM
Language tour | Dart https://dart.dev/guides/language/language-tour
void main() {
∕*
* This is a lot of work. Consider raising chickens.
Documentation comments
Documentation comments are multi-line or single-line comments that begin with ∕∕∕ or ∕**. Using ∕∕∕ on consecutive lines has
the same effect as a multi-line doc comment.
Inside a documentation comment, the analyzer ignores all text unless it is enclosed in brackets. Using brackets, you can refer to
classes, methods, �elds, top-level variables, functions, and parameters. The names in brackets are resolved in the lexical scope of
the documented program element.
Here is an example of documentation comments with references to other classes and arguments:
In the class’s generated documentation, [feed] becomes a link to the docs for the feed method, and [Food] becomes a link to
the docs for the Food class.
To parse Dart code and generate HTML documentation, you can use Dart’s documentation generation tool, dart doc. For an
example of generated documentation, see the Dart API documentation. For advice on how to structure your comments, see
Effective Dart: Documentation.
Summary
This page summarized the commonly used features in the Dart language. More features are being implemented, but we expect
that they won’t break existing code. For more information, see the Dart language speci�cation and Effective Dart.
To learn more about Dart’s core libraries, see A Tour of the Dart Libraries.
57 of 57 2/20/2022, 7:44 PM