Language Tour
A comprehensive overview of Dart's syntax and core features.
What is it?
The Language Tour is a guided introduction to Dart's syntax, features, and programming concepts. It covers everything from basic syntax to advanced language features, helping you understand how to write Dart code effectively.
Why does it exist?
The Language Tour exists to:
- Provide a complete overview of Dart's capabilities
- Help developers learn Dart quickly and efficiently
- Serve as a reference for Dart's syntax and features
- Demonstrate idiomatic Dart code patterns
- Bridge the gap between beginner and advanced concepts
Basic Syntax
Hello World
// The entry point of every Dart program
void main() {
print('Hello, World!');
}
Comments
// Single line comment
/*
Multi-line comment
spanning multiple lines
*/
/// Documentation comment for classes and functions
/// Use this to document your API
Semicolons
// Every statement ends with a semicolon
var name = 'Dart';
print(name);
// Except for curly braces and function bodies
void greet() {
print('Hello');
}
Variables
Variable Declaration
// Explicit type
String name = 'Alice';
// Type inference with var
var age = 25;
// Type inference with final (runtime constant)
final height = 1.75;
// Compile-time constant
const pi = 3.14159;
// Late initialization
late String description;
description = 'Initialized later';
Variable Types
// Numbers
int count = 10;
double price = 19.99;
num number = 42; // Can be int or double
// Strings
String greeting = 'Hello';
String multiline = '''
This is a
multi-line string
''';
// Booleans
bool isActive = true;
// Lists
List<String> names = ['Alice', 'Bob'];
var numbers = [1, 2, 3];
// Maps
Map<String, int> scores = {'Alice': 95, 'Bob': 87};
var scoreMap = {'Alice': 95};
// Sets
Set<String> uniqueNames = {'Alice', 'Bob', 'Alice'};
Null Safety
// Non-nullable (default)
String name = 'Alice'; // Cannot be null
// Nullable
String? maybeName = null;
// Null-aware operators
String displayName = maybeName ?? 'Guest'; // Fallback
String? upperName = maybeName?.toUpperCase(); // Null-safe access
// Non-null assertion (use with caution)
String definitelyName = maybeName!;
Functions
Function Declaration
// Basic function
int add(int a, int b) {
return a + b;
}
// Arrow syntax (single expression)
int multiply(int a, int b) => a * b;
// Void return
void greet(String name) {
print('Hello, $name');
}
Parameters
// Required positional parameters
void display(String name, int age) {
print('$name is $age years old');
}
// Optional positional parameters
void display(String name, [int? age]) {
if (age != null) {
print('$name is $age years old');
} else {
print(name);
}
}
// Named parameters
void display({required String name, int? age}) {
print('$name ${age != null ? 'is $age' : ''}');
}
// Default parameter values
void greet(String name, {String greeting = 'Hello'}) {
print('$greeting, $name');
}
Anonymous Functions
// Assign to variable
var multiply = (int a, int b) => a * b;
// Inline function
var numbers = [1, 2, 3];
numbers.forEach((number) {
print(number);
});
// Arrow syntax for single expression
numbers.forEach((number) => print(number));
Control Flow
If-Else
if (score > 90) {
print('Excellent');
} else if (score > 70) {
print('Good');
} else {
print('Needs improvement');
}
Switch-Case
switch (grade) {
case 'A':
print('Excellent');
break;
case 'B':
print('Good');
break;
case 'C':
print('Average');
break;
default:
print('Unknown grade');
}
// Switch with patterns (Dart 3+)
switch (value) {
case 0:
print('Zero');
break;
case 1:
case 2:
print('Small number');
break;
case int x when x > 10:
print('Large number: $x');
break;
}
Loops
// For loop
for (var i = 0; i < 5; i++) {
print(i);
}
// For-in loop
for (var name in names) {
print(name);
}
// While loop
var i = 0;
while (i < 5) {
print(i);
i++;
}
// Do-while loop
var j = 0;
do {
print(j);
j++;
} while (j < 5);
Collections
Lists
// Creating lists
List<String> names = ['Alice', 'Bob', 'Charlie'];
var numbers = [1, 2, 3];
// Empty list
List<String> empty = [];
// Fixed-length list
var fixed = List<int>.filled(3, 0);
// List operations
names.add('David');
names.insert(1, 'Eve');
names.remove('Bob');
names.removeAt(0);
names.clear();
// Accessing elements
String first = names[0];
String last = names[names.length - 1];
Sets
// Creating sets
Set<String> uniqueNames = {'Alice', 'Bob', 'Charlie'};
var numbers = {1, 2, 3};
// Empty set
Set<int> empty = {};
// Set operations
uniqueNames.add('David');
uniqueNames.remove('Bob');
bool contains = uniqueNames.contains('Alice');
// Set operations
var set1 = {1, 2, 3};
var set2 = {2, 3, 4};
var union = set1.union(set2); // {1, 2, 3, 4}
var intersection = set1.intersection(set2); // {2, 3}
var difference = set1.difference(set2); // {1}
Maps
// Creating maps
Map<String, int> scores = {
'Alice': 95,
'Bob': 87,
'Charlie': 92,
};
var scoreMap = {'Alice': 95, 'Bob': 87};
// Map operations
scores['David'] = 88;
scores.remove('Bob');
bool contains = scores.containsKey('Alice');
// Iterating maps
for (var entry in scores.entries) {
print('${entry.key}: ${entry.value}');
}
Classes
Basic Class
class Person {
String name;
int age;
// Constructor
Person(this.name, this.age);
// Methods
void sayHello() {
print('Hello, I am $name');
}
// Getters
bool get isAdult => age >= 18;
// Setters
set age(int value) {
if (value >= 0) {
_age = value;
}
}
}
// Usage
var person = Person('Alice', 25);
person.sayHello();
print(person.isAdult);
Constructor Types
class Point {
double x, y;
// Generative constructor
Point(this.x, this.y);
// Named constructor
Point.origin() : this(0, 0);
// Factory constructor
factory Point.fromJson(Map<String, double> json) {
return Point(json['x']!, json['y']!);
}
// Redirecting constructor
Point.zero() : this(0, 0);
}
// Usage
var p1 = Point(3, 4);
var p2 = Point.origin();
var p3 = Point.fromJson({'x': 1.0, 'y': 2.0});
Inheritance
// Base class
class Animal {
String name;
Animal(this.name);
void speak() {
print('$name makes a sound');
}
}
// Derived class
class Dog extends Animal {
Dog(String name) : super(name);
@override
void speak() {
print('$name barks');
}
}
// Usage
var dog = Dog('Rex');
dog.speak(); // Rex barks
Mixins
mixin Flyable {
void fly() {
print('Flying');
}
}
mixin Swimmable {
void swim() {
print('Swimming');
}
}
class Duck extends Animal with Flyable, Swimmable {
Duck(String name) : super(name);
}
// Usage
var duck = Duck('Donald');
duck.fly(); // Flying
duck.swim(); // Swimming
Records
Record Types
// Positional record
(int, String) person = (25, 'Alice');
var age = person.$1;
var name = person.$2;
// Named record
({int age, String name}) person = (age: 25, name: 'Alice');
var age = person.age;
var name = person.name;
// Record with both
(int, {String name}) person = (25, name: 'Alice');
Record Usage
// Function returning multiple values
(String, int) getPerson() {
return ('Alice', 25);
}
// Destructuring
var (name, age) = getPerson();
print('$name is $age years old');
// Pattern matching
switch (getPerson()) {
case ('Alice', int age):
print('Alice is $age');
case (String name, 25):
print('$name is 25');
}
Patterns
Pattern Matching
// Variable pattern
var (x, y) = (1, 2);
// List pattern
var [a, b, c] = [1, 2, 3];
// Map pattern
var {'name': name, 'age': age} = {'name': 'Alice', 'age': 25};
// Switch with patterns
switch (value) {
case 0:
print('Zero');
case int x when x > 0:
print('Positive: $x');
case String s:
print('String: $s');
}
Destructuring
// Record destructuring
var (x, y) = (1, 2);
// Class destructuring (with pattern)
class Point {
final int x, y;
Point(this.x, this.y);
}
var Point(x: x, y: y) = Point(1, 2);
// Map destructuring
var {'name': name, 'age': age} = {'name': 'Alice', 'age': 25};
Asynchronous Programming
Future
// Creating a Future
Future<String> fetchData() {
return Future.delayed(
Duration(seconds: 1),
() => 'Data loaded',
);
}
// Using Future
void main() {
fetchData().then((data) {
print(data);
});
}
Async/Await
// Async function
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 1));
return 'Data loaded';
}
// Using await
void main() async {
String data = await fetchData();
print(data);
}
// Error handling
try {
String data = await fetchData();
print(data);
} catch (e) {
print('Error: $e');
}
Streams
// Creating a Stream
Stream<int> countStream() async* {
for (var i = 1; i <= 5; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
// Using a Stream
void main() async {
await for (var value in countStream()) {
print(value);
}
}
Exceptions
Try-Catch
try {
int result = 10 ~/ 0;
} on IntegerDivisionByZeroException {
print('Cannot divide by zero');
} catch (e) {
print('Error: $e');
} finally {
print('Cleanup');
}
Throwing Exceptions
void validateAge(int age) {
if (age < 0) {
throw ArgumentError('Age cannot be negative');
}
if (age < 18) {
throw Exception('Must be at least 18');
}
}
// Usage
try {
validateAge(-1);
} catch (e) {
print('Validation failed: $e');
}
Generics
Generic Classes
class Box<T> {
T value;
Box(this.value);
T getValue() => value;
}
// Usage
Box<String> stringBox = Box('Hello');
Box<int> intBox = Box(42);
Generic Functions
// Generic function
T identity<T>(T value) {
return value;
}
// Usage
var stringResult = identity('Hello');
var intResult = identity(42);
// Type bounds
T max<T extends Comparable<T>>(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
Common Operators
Equality and Comparison
// Equality
var equals = a == b;
var notEquals = a != b;
// Comparison
var greater = a > b;
var greaterOrEqual = a >= b;
var less = a < b;
var lessOrEqual = a <= b;
// Null-aware operators
var value = maybeValue ?? defaultValue; // Null-aware default
var result = object?.property; // Null-aware access
Type Operators
// Type check
bool isString = value is String;
// Type cast
String stringValue = value as String;
// Value assignment
var value ??= defaultValue; // Assign if null
Cascade Notation
var list = [1, 2, 3]
..add(4)
..add(5)
..remove(1);
// Equivalent to:
var list = [1, 2, 3];
list.add(4);
list.add(5);
list.remove(1);
Summary
Dart provides a comprehensive set of features for modern application development. From its clean syntax and strong typing to advanced features like async/await and pattern matching, Dart is designed to be productive, performant, and enjoyable to use.
Next Steps
Now that you've seen the language tour, explore specific topics:
Did You Know?
- Dart is compiled to native code for mobile and desktop
- The language supports both JIT and AOT compilation
- Dart's type system is sound and null-safe
- Dart 3 introduced records and patterns
- The language is continuously evolving with community input