Sei sulla pagina 1di 26

Dart Basics

You’re looking to get started with Flutter development, but have only just found out
that Flutter uses the Dart programming language? This tutorial will introduce you to
some Dart basics so you can get up and running with the language for Flutter
development.

Dart was released by Google in 2011 and was initially designed as a replacement for
JavaScript. Since then, the release of the Flutter SDK for iOS, Android, and web
development has put a new spotlight on the Dart language. The most recent version
of Dart at the time of this recording is 2.4.

Dart has many similarities to other languages you may already be familiar with, such
as Java, C#, Swift, and Kotlin. Dart has the following language characteristics:

▪ Statically typed
▪ Type inference
▪ String expressions
▪ Multi-paradigm including OOP and functional
▪ Can mimic dynamic types using dynamic

In addition to its use for mobile and web development, Flutter is the development kit
for Fuchsia, an experimental operating system under development at Google.

This tutorial will introduce you to Dart basics such as:

▪ Variables, data types, and operators


▪ Conditionals and loops
▪ Functions, anonymous functions, and closures
▪ Arrow function syntax
Getting Started
To get up and running quickly for learning Dart, you’re best bet is to use
the DartPad editor, found at https://dartpad.dartlang.org:

DartPad is setup like a typical IDE. There is:

▪ An Editor pane on the left


▪ A Run button to run code in the editor
▪ A Console on the upper right showing output
▪ An Info panel on the bottom right showing information highlighted code
▪ A Samples dropdown to show some sample code
▪ A Share button you can use to share DartPad files you’ve created

Down in the lower bottom right, there’s a checkbox to show some more panels related to
using Dart for web programming, and some text showing the current version of Dart being
used in DartPad.

If you prefer, you can install the Dart SDK locally on your machine. One way to do so is
to install the Flutter SDK. Installing flutter will also install the Dart SDK.

You can also just install the Dart SDK directly by visiting here.
Core Concepts
Dart programs begin with a call to the `main` function, and the syntax for `main` looks very
similar to the syntax for `main` in other languages like C, Swift, or Kotlin.

Clear out all the code in the default DartPad, and add a `main` function to the editor:

void main() {

The main function is preceded by a return type, which in Dart is void , meaning
The main function is preceded by a return type, which in Dart is void , meaning nothing is
returned. The parentheses after main indicate that this is a function definition, and the curly
braces contain the body of the function. Inside main , you add the Dart code for your
program.

Variables, Comments, and Data Types

The first thing we’ll add to main is a variable assignment statement. Variables hold the data
that your program will work on. You can think of a variable like a box in your computer’s
memory that holds a value. Each box has a name, the name for the variable. You use
the var keyword in Dart to denote a variable.

Add a new variable to main :

var myAge = 35;

Like C and Java, each Dart statement ends in a semicolon. You’ve created a myAge variable
set it equal to 35.

You can use the built-in print function in Dart to print the variable to the console, so add
that call after the variable:

print(myAge); // 35
Click the Run button in DartPad to run the code, and you’ll see the variable printed out in the
console on the upper right.

Comments in Dart look just like those in C in other languages: text either following // on a
line, or text within /* … */ blocks.

// This is a comment.

print(myAge); // This is also a comment.

/*

And so is this.

*/

If you put the cursor in the editor over the myAge name, you’ll see in the lower right panel
that Dart has inferred that myAge is an int variable, thanks to being initialized with the
integer value 35. Like Swift and Kotlin, Dart uses type inference to attempt to figure out the
type of your date if you do not specify it directly.

An alternative to using type inference is to replace the var keyword with the specific type
you want to use:

int yourAge = 27;

print(yourAge); // 27
Similar to many languages such as C, Java, Swift, and Kotlin, Dart is statically typed. That
means that each variable in Dart has a type that must be known when the code is compiled,
and the type of the variable cannot change when the program is run.

This contrasts with languages like Python and Javascript that are dynamically typed,
meaning variables can hold different kinds of data when being run, and the type does not
need to be known when the code is compiled.

Basic Dart Types

Dart uses int for integers, double for floating points, and bool for booleans. int s
and double s are both derived from a type named num . You use the String type to represent
sequences of characters. Dart also has a keyword dynamic which lets you mimic dynamic
typing in the statically typed Dart.

You can also use type inference for types other than int . Enter a variable pi equal to 3.14
like so:

var pi = 3.14;

print(pi); // 3.14

pi is inferred to be a double since you used a floating-point value to initialize it. You can
see that in the Dart info panel

You can also just use double as the type instead of var :
double c = 299792458;

print(c); // 299792458

In this case, you’ve initialized c , the symbol for the speed of light, with an int , but because
you specified the type as double, c is in fact a double . Dart will convert the int to
a double in order to initialize c . So unlike Swift, Dart has implicit type-conversion.

The dynamic Keyword

If you use the dynamic keyword instead of var , you get what is effectively a dynamically-
typed variable:

dynamic numberOfKittens;

You can set numberOfKittens to a String using quotes (see below for more on
the String type)

numberOfKittens = 'There are no kittens!';

print(numberOfKittens); // There are no kittens!

numberOfKittens has a type, as it must since Dart has static typing. But that type
is dynamic , which means you can assign other values with other types to it. So you can
assign an int value below your print statement.

numberOfKittens = 0;

print(numberOfKittens); // 0

Or if you have a kitten in Schrödinger’s box, you could assign a double value:

numberOfKittens = 0.5;

print(numberOfKittens); // 0.5

Go ahead and click Run to see the three different values for numberOfKittens all printed
out in the console. In each case, the type of numberOfKittens remains dynamic , even
though the variable itself holds values of different types.
The bool type is used to hold values of either true or false.

bool areThereKittens = false;

print(areThereKittens); // false

But, if you look inside the Schrödinger box, you may switch to having a real live kitten:

numberOfKittens = 1;

areThereKittens = true;

print(areThereKittens); // true

Run the code again to see your boolean values in the console. It’s a good thing you looked in
the box!

Operators
Dart has all the usual operators you’re familiar with from other languages like C, Swift, and
Kotlin.

There are arithmetic operators, equality, increment and decrement, comparison,


and logical operators.

Dart also allows for operator overloading like C++ and Kotlin, but that’s beyond the scope
of this tutorial.

The arithmetic operators work just liked you’d expect. Add a bunch of operations to your
DartPad:

print(40 + 2); // 42

print(44 - 2); // 42

print(21 * 2); // 42

print(84 / 2); // 42

See more here on 42.


You can initialize variables using arithmetic expressions:

var atltuae = 84.0 / 2;

print(atltuae); // 42

Dart converts the int to a double prior to the operation, so that the resulting variable is
inferred to be a double .

Dart has double-equals equality and not-equals operators:

print(42 == 43); // false

print(42 != 43); // true

There are pre- and post-fix increment and decrement operators:

print(atltuae++); // 42

print(--atltuae); // 42

Because the use of increment is postfix, 42 is printed before the increment occurs. The
decrement is prefix, so 43 is decremented to 42 and then the value 42 is printed.

Dart has the typical comparison operators like less than and greater than or equal to.

print(42 < 43); // true

print(42 >= 43); // false

There are also the usual compound arithmetic/assignment operators

atltuae += 1; print(atltuae); // 43

atltuae -= 1; print(atltuae); // 42

atltuae *= 2; print(atltuae); // 84

atltuae /= 2; print(atltuae); // 42

And Dart has the usual modulo operator.


print(392 % 50); // 42

The logical operators such as && for and and || for or look just like those from other
languages.

print((41 < atltuae) && (atltuae < 43)); // true

print((41 < atltuae) || (atltuae > 43)); // true

And the negation operator is the exclamation mark, turning false to true and true to false.

print(!(41 < atltuae)); // false

Strings
The Dart string type is String . Strings are expressed in Dart using text surrounded
by either single or double quotes.

Like for the other types we've seen, you can use either var and type inference or String to
create a string variable:

var firstName = 'Albert';

String lastName = "Einstein";

Similar to languages like Kotlin and Swift, you can embed values and expressions inside
strings to create new strings, using the dollar sign symbol $.

var physicist = "$firstName $lastName";

print(physicist); // Albert Einstein

You can combine adjacent strings, for example, long strings that go multiple lines, simply by
placing the strings next to one another or on separate lines:

var quote = 'If you can\'t' ' explain it simply\n'

"you don't understand it well enough.";

print(quote);
// If you can't explain it simply

// you don't understand it well enough.

Here in the first string, you used single quotes and so used an escape sequence \' to embed a
quotation mark for can't into the string. The escape sequences used in Dart are similar to
those used in other C-like languages, for example, \n for a newline.

Since you used double-quotes to delimit the second string, you did not need an escape
sequence for the single quote on don't .

You can also combine strings using the + operator:

var energy = "Mass" + " times " + "c squared";

print(energy); // Mass times c squared

You can use triple quotes to have a string run multiple lines and preserve formatting:

var model = """

I'm not creating the universe.

I'm creating a model of the universe,

which may or may not be true.""";

print(model);

// I'm not creating the universe.

// I'm creating a model of the universe,

// which may or may not be true.

If you need to have escape sequences shown within the string, you can use raw strings,
which are prefixed by r.

var rawString = r"If you can't explain it simply\nyou don't understand it


well enough.";

print(rawString);

// If you can't explain it simply\nyou don't understand it well enough.


Go ahead and click Run in DartPad to see all your strings in the console.

Immutability
Dart has the keywords const and final for values that don't change. const is used for
values that are known at compile-time, final is used for values that don't have to be known
at compile-time but cannot be re-assigned after being initialized. final acts like val in
Kotlin or let in Swift.

You can use const and final in place of var and let type inference determine the type:

const speedOfLight = 299792458;

print(speedOfLight); // 299792458

So speedOfLight is inferred to be an int , as you can see in the info panel of DartPad.

final means immutable, and final values cannot be re-assigned. You can also explicitly
state the type with either final or const :

final planet = 'Jupiter';

// final planet = 'Mar'; // error: planet is immutable

final String moon = 'Europa';

print('$planet has a moon $moon');

// Jupiter has a moon Europa

Nullability

For any variable, no matter the type, if you do not initialize the variable, the variable will be
given the value null , which means nothing is stored in the variable.

This is in contrast to languages like Swift and Kotlin, for which you have to explicitly declare
a variable as being nullable (aka optional in Swift). Default types in those languages are non-
nullable.

It turns out that all Dart types, even basic types like int and double , are derived from a type
named Object . And if you don't initialize an object, it takes on a null value.
You'll see here some ways to handle null values safely in Dart, but it does not go quite as far
as optionals in Swift or nullables in Kotlin.

Create three variables of different types and then immediately print them.

int age;

double height;

String err;

print(age); // null

print(height); // null

print(err); // null

You'll see that each of the variables is null in the console.

Dart has some null-aware operators you can use for working with null values.

The double-question mark operator ?? is like the "Elvis operator" in Kotlin: it will return the
left-hand operand if it's not-null, otherwise the right-hand value:

var error = err ?? "No error";

print(error); // No error

There's a corresponding assignment operator ??= that does similar:

err ??= error;

print(err); // No error

Since you just made error non-null with a value "No error", the err value now picks up that
non-null value on this assignment.

There's also an operator ?. that protects you from accessing properties on null objects. It will
return null if the object itself is null. Otherwise, it returns the value of the property on the
right-hand side:

print(age?.isEven); // null
If you tried just age.isEven and age was null , you'd get an Uncaught exception.

Control Flow
Control flow lets you dictate that certain lines of code are executed, skipped over, or
repeated. Control flow is handled in Dart with conditionals and loops.

Conditionals
The most basic form of control flow is deciding whether to execute or skip over certain parts
of your code, depending on conditions that occur as your program runs. The language
construct for handling conditions is the if / else statement. if / else in Dart looks nearly
identical to the use in other C-like languages.

Suppose you have an animal variable that's currently a fox.

var animal = 'fox';

You can use an if statement to check whether the animal is a cat or dog, and run some
corresponding code if so.

if (animal == 'cat' || animal == 'dog') {

print('Animal is a house pet.');

Here you've used the equality and or operators to create a bool value inside the condition for
the if statement.

You can use an else clause to run alternative code if the condition is false:

} else {

print('Animal is NOT a house pet.');

// Animal is NOT a house pet.


You can also combine multiple if / else statements into an if / else if / else construct:

if (animal == 'cat' || animal == 'dog') {

print('Animal is a house pet.');

} else if (animal == 'rhino') {

print('That\'s a big animal.');

} else {

print('Animal is NOT a house pet.');

// Animal is NOT a house pet.

You can have as many else if branches in between if and else as needed.

While Loops
Loops let you repeat code a certain number of times or based on certain conditions. The latter
are handled by while loops.

There are two forms of while loop in Dart, while and do-while . The difference is that
for while , the loop condition is before the code block, and in do-while the condition is
after. So for do-while , the code block is guaranteed to run at least one time.

Create a variable i initialized to 1:

var i = 1;

You can use a while loop to print i while incrementing it, and set the condition to be
that i is less than 10:
while (i < 10) {

print(i);

i++;

// 1

// 2

// 3

// 4

// 5

// 6

// 7

// 8

// 9

Run the code and you see the numbers 1 to 9 printed out by the while loop.

Reset i in DartPad and then add a do-while loop:

i = 1;

do {

print(i);

++i;

} while (i < 10);

// 1

// 2

// 3

// 4

// 5

// 6
// 7

// 8

// 9

The results here are the same as before, just this time, the loop body ran once before the loop
exit condition was checked.

continue and break

Dart has the usual continue and break keywords for use in loops and
elsewhere. continue will skip remaining code inside a loop and immediately go to the next
iteration. break stops the loop and continues execution after the body of the loop.

You must be careful when using continue in your code. For example, if you take the do-
while loop from above, and say you want to continue when i is equal to 5, that could result
in an infinite loop that just keeps running, depending in where you place
the continue statement:

do {

print(i);

if (i == 5) {

continue;

++i;

} while (i < 10);

// 1

// 2

// 3

// 4

// 5

// 5

// 5

// 5
// 5

// 5

// 5

// 5

// 5

// 5

// ...

The infinite loop occurs since once i is 5, you never increment i , and the condition always
stays true.

If you run this in DartPad, the infinite loop will cause the browser to hang. Instead
use break , so that the loop will end after i reaches 5:

do {

print(i);

if (i == 5) {

break;

++i;

} while (i < 10);

// 1

// 2

// 3

// 4

// 5

Run the code now and see that the loop ends after 5 iterations.
For Loops
The loops that loop a pre-determined number of times are for loops in Dart, which once again
are very similar to those from other languages.

Dart has both a C-like form of a for loop, with an initialization, loop condition, and an action,
as well a for-in loop for iterating over a collection of objects. In the first form, the
initialization runs before the first loop iteration. The condition is checked on entering each
iteration, and the action is run before starting the next iteration.

For the for-in form, a variable is set to each element in a collection of Dart objects for each
subsequent iteration of the loop. Let's say you want to sum up the values of the first 10
integers.

Create a variable for the sum:

var sum = 0;

Then use a for loop in which you initialize a loop counter i to 1, check that i is less than or
equal to 10, and increment i after every loop. Inside the loop use a compound assignment to
add i to the running sum:

for (var i = 1; i <= 10; i++) {

sum += i;

print("The sum is $sum"); // The sum is 55

Run your code in DartPad to see the sum.

An example of a Dart collection is a simple list of numbers made with square brackets:

var numbers = [1, 2, 3, 4];

You can use a for-in loop to iterate over the list:

for (var number in numbers) {

print(number);

}
// 1

// 2

// 3

// 4

The variable number takes on the value of each element of numbers as you iterate in the
loop.

Lists like numbers also have a function you can call on them named forEach , which
simplifies the previous loop down to one line:

numbers.forEach((number) => print(number));

// 1

// 2

// 3

// 4

Here you've used an anonymous function and arrow syntax, both of which you'll see later
on in the section on Functions.

Finally, like while loops, for loops can also use continue and break to control flow within
the loop. For example, if you want to skip printing the number 3, you can use
a continue statement in the for - in loop:

for (var number in numbers) {

if (number == 3) {

continue;

print(number);

// 1

// 2

// 4
switch and enum
Dart also has support for a switch statement and enumerations using enum . Consult the Dart
documentation for more on both. Like most of the rest of the Dart constructs you've seen,
they work similarly to how they work in other languages like C and Java.

Functions
Functions let you package multiple related lines of code into a single body that you can
summon to avoid repeating those lines of code throughout your Dart application:

A function consists of a return type, a function name, a parameter list in parentheses, and
then a function body enclosed in braces. The code you're turning into the function goes
inside the braces. When you call the function, you pass in arguments that match the types of
the parameters of the function.
Note: Specifying a return type on functions is optional. If you leave off the return type, values
returned from the function will either have an inferred type, or be dynamic if the type cannot be
inferred. That allows you to return values of different types from the function. Usually you'll want to
avoid this and instead specify a single return type from functions.

Typically, functions are defined either outside other functions or inside Dart classes, but you
can also nest Dart functions in one another. For example, you can add the functions in this
section inside main .

Write a new function in DartPad that will just check to see if a given string is banana.

bool isBanana(String fruit) {

return fruit == 'banana';

The function uses return to return a bool value determined by the argument passed to the
function. This function will always return the same value for any given input. If a function
does not need to return a value, you can set the return type to void , such as for
the main function.

You can call the function by passing in a string. Then you might pass the result of that call
onto print :

var fruit = 'apple';

print(isBanana(fruit)); // false

You can change the argument passed to functions, and call them again with a new argument:

fruit = 'banana';

print(isBanana(fruit)); // true

The result of calling the function depends entirely on the arguments passed in.

Optional Parameters
If a parameter to a function is optional, you can surround it with square brackets:

String fullName(String first, String last, [String title]) {

return "${title == null ? "" : "$title "}$first $last";

If an optional parameter is not included in the function call, the value used is null for the
parameter inside the function body.

Then you can call the function with or without the optional parameter:

print(fullName("Joe", "Howard"));

// Joe Howard

print(fullName("Albert", "Einstein", "Professor"));

// Professor Albert Einstein


Optional Named Arguments
With Dart functions, you can use optional named arguments by surrounding the parameter
list with braces:

bool withinTolerance({int value, int min, int max}) {

return min <= value && value <= max;

Then you can pass in arguments in a different order by supplying the parameter names with a
colon:

print(withinTolerance(min: 1, max: 10, value: 11)); // false

Like for optional parameters, arguments with optional names do not need to be added to a
function call, and the corresponding parameters will be given the value null in the
function.

Default Values
You can also assign default values to one or more parameters using equals:

bool withinTolerance({int value, int min = 0, int max = 10}) {

return min <= value && value <= max;

You can then leave off the parameters with default values when calling the function.

print(withinTolerance(value: 5)); // true

Run your code to see your new functions in action.

First-Class Functions

Dart has support for what are called first-class functions. The term means that functions are
treated like any other data type, that is, they can be assigned to variables, passed as
arguments, and returned from other functions.
You can use the Function type to specify that a parameter named op is a function itself:

int applyTo(int value, int Function(int) op) {

return op(value);

So if you have a function named square :

int square(int n) {

return n * n;

You can pass square to applyTo as an argument:

print(applyTo(3, square)); // 9

You can assign a function to a variable:

var op = square;

Then you can call the function on the variable as if it were an alias for the original function:

print(op(5)); // 25

You'll see more about returning functions from other functions a bit later.

Anonymous Functions and Closures


The functions you've seen so far have been named functions, functions with a
name. Anonymous functions are just what you might expect, functions without a name. You
can also leave off the return type which will be inferred. So you just need a parameter list and
a function body for an anonymous function.

You can assign an anonymous function to a variable:


var multiply = (int a, int b) {

return a * b;

};

The right-hand-side consists of a parameter list and a function body.

Since multiply now holds an anonymous function, you can call it as you would any other
function:

print(multiply(14, 3)); // 42

You've seen a preview earlier of lists and the forEach function. forEach is a great example
of using an anonymous function.

So if you have a list of numbers:

numbers = [1, 2, 3];

You can call forEach on the list and pass in an anonymous function that triples an element
and prints out the tripled value:

numbers.forEach((number) {

var tripled = number * 3;

print(tripled);

// 3

// 6

// 9

});

You can return an anonymous function from another function:

Function applyMultiplier(num multiplier) {

return (num value) {


return value * multiplier;

};

This is useful for generating functions with a given behavior but with varying input parameter
values. So the return value here is a function that takes one num parameter and multiplies it
by the multiple used to generate the function.

An example is creating a variable named triple which multiplies its input by 3:

var triple = applyMultiplier(3);

You can calling triple with either type of num:

print(triple(6)); // 18

print(triple(14.0)); // 42

Anonymous functions in Dart act as closures, which means they "close-over" variables
defined outside of themselves. For example, the return value of
the applyMultiplier function above is a closure that has access to the multiplier variable
defined elsewhere, in that case in the parameter list for applyMultiplier itself.

Arrow Syntax

When a Dart function, either named or anonymous, consists of just one line of code, you can
reduce the function body using the Dart arrow syntax.

For example, multiply above becomes:

var multiply = (int a, int b) => a * b;

You've removed the braces and the return statement.

You can also use arrow syntax with applyMultiplier :

Function applyMultiplier(num multiplier) =>

(num value) => value * multiplier;


You've used arrow syntax twice here: the first is denoting the return value for
the applyMultiplier function, the second is within the return value itself, which is an
anonymous function.

In the example just above using forEach , you cannot use arrow syntax, since the body of the
function you're passing to forEach has more than one line of code.

Where to Go From Here?


That concludes this brief tour of the basics of Dart. You should now have a better
understanding of the Dart code you see when learning how to build Flutter apps.

You can download all the code for this tutorial by clicking the Download Materials button at
the top or bottom of the page. You can either paste the code in the main.dart file into
DartPad or use the Dart SDK to run the file.

As mentioned in the introduction, you can go beyond the basics and learn more
about Object-Oriented Programming in Dart as well as Dart collection types such as lists,
sets, and maps, in our course Programming in Dart - Fundamentals, on which this short
tutorial is based.

Check out the official Dart documentation to learn about intermediate and advanced parts of
Dart:

▪ Iterables and Generators


▪ Exceptions
▪ Runes and symbols
▪ Asynchronous Dart with isolates, streams, futures and async / await

We'll be covering these and other Dart topics in future tutorials and video courses.

I hope you enjoyed this brief introduction to Dart basics. Please write to us in the forums
below if you have questions or comments!

Potrebbero piacerti anche