Dart Basics
Get an introduction to the basics of the Dart programming language, used for development with the Flutter SDK for mobile, web and beyond. By Jonathan Sande.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Dart Basics
35 mins
- Getting Started
- Why Dart?
- Core Concepts
- Variables, Comments and Data Types
- Comments
- Data Types
- Basic Dart Types
- The Dynamic Keyword
- Booleans
- Operators
- Arithmetic Operators
- Equality Operators
- Comparison Operators
- Logical Operators
- Strings
- Escaping Strings
- Immutability
- Nullability
- Null-Aware Operators
- Control Flow
- Conditionals
- If Statements
- Else Statements
- While Loops
- Testing the While Loop
- Trying Out the Do-While Loop
- Continue and Break
- For Loops
- Collections
- Lists
- Working With List Elements
- Maps
- Functions
- Defining Functions
- Working With Functions
- Nesting Functions
- Optional Parameters
- Named Parameters and Default Values
- Anonymous Functions
- Using Anonymous Functions
- Where to Go From Here?
Collections
Collections are useful for grouping related data. Dart includes several different types of collections, but this tutorial will cover the two most common ones: List
and Map
.
Lists
Lists in Dart are similar to arrays in other languages. You use them to maintain an ordered list of values. Lists are zero-based, so the first item in the list is at index 0:
Here’s a list of different desserts:
List desserts = ['cookies', 'cupcakes', 'donuts', 'pie'];
You enclose the elements of a list in square brackets: [ ]
. You use commas to separate the elements.
At the beginning of the line, you can see that the type is List
. You’ll notice there is no type included. Dart infers that list has type List
.
Here’s a list of integers:
final numbers = [42, -1, 299792458, 100];
Click numbers
in DartPad and you’ll see that Dart recognizes the type as a List
of int
.
Working With List Elements
To access the elements of a list, use subscript notation by putting the index number between square brackets after the list variable name. For example:
final firstDessert = desserts[0];
print(firstDessert); // cookies
Since list indices are zero-based, desserts[0]
is the first element of the list.
Add and remove elements with add
and remove
respectively:
desserts.add('cake');
print(desserts);
// [cookies, cupcakes, donuts, pie, cake]
desserts.remove('donuts');
print(desserts);
// [cookies, cupcakes, pie, cake]
Run the code to see the results.
Earlier, you learned about for
loops. Dart’s for-in
loop that works especially well with lists. Try it out:
for (final dessert in desserts) {
print('I love to eat $dessert.');
}
// I love to eat cookies.
// I love to eat cupcakes.
// I love to eat pie.
// I love to eat cake.
You don’t need to use an index. Dart just loops through every element of desserts
and assigns it each time to a variable named dessert
.
Getting hungry? Well, you can’t have any dessert until you’ve finished your vegetables. :]
Maps
When you want a list of paired values, Map
is a good choice. Dart Map
s are similar to dictionaries in Swift and maps in Kotlin.
Here’s an example of a map in Dart:
Map<String, int> calories = {
'cake': 500,
'donuts': 150,
'cookies': 100,
};
You surround Map
s with curly braces { }
. Use commas to separate a map’s elements.
Elements of a map are called key-value pairs, where the key is on the left of a colon and the value is on the right.
You find a value by using the key to look it up, like this:
final donutCalories = calories['donuts'];
print(donutCalories); // 150
The key, 'donuts'
, is inside the square brackets after the map name. In this case, it maps to a value of 150
.
Click donutCalories
in DartPad and you’ll see that the inferred type is int?
rather than int
. That’s because, if a map doesn’t contain the key that you’re looking up, it’ll return a null
value.
Add a new element to a map by specifying the key and assigning it a value:
calories['brownieFudgeSundae'] = 1346;
print(calories);
// {cake: 500, donuts: 150, cookies: 100, brownieFudgeSundae: 1346}
Run that code and you’ll see the map printed in horizontal format with your new dessert at the end.
Functions
Functions let you package multiple related lines of code into a single body. You then summon the function to avoid repeating those lines of code throughout your Dart app.
A function consists of the following elements:
- Return type
- Function name
- Parameter list in parentheses
- Function body enclosed in brackets
Defining Functions
The code you’re turning into a function goes inside the curly brackets. When you call the function, you pass in arguments that match the types of the parameters of the function.
Next, you’ll write a new function in DartPad that will check to see if a given string is banana:
bool isBanana(String fruit) {
return fruit == 'banana';
}
The function uses return
to return a bool
. The argument you pass to the function determines the bool
.
This function will always return the same value type for any given input. If a function doesn’t need to return a value, you can set the return type to void
. main
does this, for example.
Working With Functions
You can call the function by passing in a string. You might then pass the result of that call to print
:
void main() {
var fruit = 'apple';
print(isBanana(fruit)); // false
}
Nesting Functions
Typically, you define functions either outside other functions or inside Dart classes. However, you can also nest Dart functions. For example, you can nest isBanana
inside main
.
void main() {
bool isBanana(String fruit) {
return fruit == 'banana';
}
var fruit = 'apple';
print(isBanana(fruit)); // false
}
You can also change the argument you to a function, then call it again with the new argument:
fruit = 'banana';
print(isBanana(fruit)); // true
The result of calling the function depends entirely on the arguments you pass in.
Optional Parameters
If a parameter to a function is optional, you can surround it with square brackets and make the type nullable:
String fullName(String first, String last, [String? title]) {
if (title == null) {
return '$first $last';
} else {
return '$title $first $last';
}
}
In this function, title
is optional. It will default to null
if you don’t specify it.
Now, 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
Named Parameters and Default Values
When you have multiple parameters, it can be confusing to remember which is which. Dart solves this problem with named parameters, which you get by surrounding the parameter list with curly brackets: { }
.
These parameters are optional by default, but you can give them default values or make them required by using the required
keyword:
bool withinTolerance({required int value, int min = 0, int max = 10}) {
return min <= value && value <= max;
}
value
is required, while min
and max
are optional with default values.
With named parameters, you can pass in arguments in a different order by supplying the parameter names with a colon:
print(withinTolerance(min: 1, max: 5, value: 11)); // false
You can 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.