---
title: "Dart"
description: "Dart is a statically-typed, strongly null-safe programming language optimized for building fast, multi-platform applications with excellent null safety, async/await, and object-oriented features."
author: "Mohammad Abu Mattar"
canonical: https://mkabumattar.com/cheatsheets/dart
---

# Dart

Dart is a statically-typed, strongly null-safe programming language designed for building fast, multi-platform applications. Created by Google, Dart combines the best features of many languages while providing excellent tooling and powerful features for web, server, and mobile development.

Key features include:

- **Strong Null Safety**: The type system enforces null safety, preventing null reference errors at compile-time.
- **Async/Await**: First-class support for asynchronous programming with futures, streams, and async/await syntax.
- **Object-Oriented**: Full OOP support with classes, inheritance, mixins, and abstract classes.
- **Generics**: Powerful generic type system for reusable, type-safe code.
- **Extensions**: Extend existing types with new methods without inheritance.
- **Type Inference**: Automatic type inference while maintaining strict type safety.
- **Hot Reload**: Rapid development cycle with instant code changes during debugging.

Browse the categories below to explore Dart syntax, advanced features, and best practices.

## Getting Started

Fundamental Dart concepts and basic syntax for beginners.

### Hello World

Basic Dart program structure with main function and output.

**Keywords:** hello world, main, print, output

#### Simple Hello World

```dart
void main() {
  print('Hello, World!');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Hello, World!
```

A basic Dart program with main function that prints a greeting using print().

- Every Dart application must have a main() function.
- main() is the entry point of the program.

#### Multiple print statements

```dart
void main() {
  print('Welcome to Dart');
  print('Dart is awesome!');
  print('Multi-platform development');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Welcome to Dart
Dart is awesome!
Multi-platform development
```

Demonstrates calling print() multiple times to output different lines.

- print() adds a newline automatically.
- Statements must end with semicolons in Dart.

#### String interpolation

```dart
void main() {
  String name = 'Dart';
  int version = 3;
  print('Welcome to $name version $version!');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Welcome to Dart version 3!
```

Uses string interpolation with $ syntax to embed variables in strings.

- Use $ for simple variable insertion.
- Use ${expression} for complex expressions in strings.

**Best practices:**

- Use print() for debugging output in Dart programs.
- Keep the main function as the entry point and delegate to other functions.
- Use string interpolation instead of string concatenation for clarity.

**Common errors:**

- **Missing main function**: Every Dart program must have a void main() function.
- **Missing semicolons**: Dart requires semicolons at the end of statements.

### Variables

Declaring and working with variables in Dart, including type inference and null safety.

**Keywords:** variables, var, dynamic, late, final, const

#### Variable declaration with type annotation

```dart
void main() {
  String name = 'Alice';
  int age = 30;
  double salary = 50000.50;
  bool isActive = true;

  print('$name is $age years old');
  print('Salary: $salary');
  print('Active: $isActive');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Alice is 30 years old
Salary: 50000.5
Active: true
```

Demonstrates explicit variable declaration with type specification.

- Type annotation comes before variable name.
- Dart supports String, int, double, bool, and other types.

#### Type inference with var

```dart
void main() {
  var name = 'Bob';
  var count = 5;
  var price = 19.99;

  print('Name: $name');
  print('Count: $count');
  print('Price: $price');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Name: Bob
Count: 5
Price: 19.99
```

Uses var keyword for type inference; Dart infers type from the assigned value.

- var keyword makes code cleaner when type is obvious.
- Dart still enforces strict typing after inference.

#### Final and const variables

```dart
void main() {
  final String finalName = 'Charlie';
  const int maxRetries = 3;

  print('Final name: $finalName');
  print('Max retries: $maxRetries');

  // finalName = 'David'; // Error: can't assign
  // maxRetries = 5; // Error: can't assign
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Final name: Charlie
Max retries: 3
```

Demonstrates final variables (runtime constant) and const (compile-time constant).

- final variables cannot be reassigned after initialization.
- const is for compile-time constants; more restrictive than final.

**Best practices:**

- Use var for local variables when type is obvious.
- Use explicit types for function parameters and return types.
- Use final for variables that won't change.
- Use const for compile-time constants.

**Common errors:**

- **Null reference exception**: Use null-aware operators (?, ??, ?.) for nullable types.
- **Trying to reassign final variable**: final variables cannot be modified; use var instead if needed.

**Advanced notes:**

- **Late variables:** Use late keyword for variables initialized later: late String value;
- **Dynamic type:** Avoid dynamic when possible; use specific types or var for type safety.

### Null Safety

Understanding Dart's null safety feature and nullable vs non-nullable types.

**Keywords:** null safety, nullable, non-nullable, null-aware operators

#### Non-nullable and nullable types

```dart
void main() {
  String name = 'Alice'; // Non-nullable
  String? nickName; // Nullable

  // name = null; // Error: can't assign null
  nickName = 'Ali';
  nickName = null; // OK

  print('Name: $name');
  print('Nickname: $nickName');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Name: Alice
Nickname: null
```

Demonstrates non-nullable (String) and nullable (String?) type declarations.

- By default, types are non-nullable in Dart.
- Add ? to make a type nullable.

#### Null-aware operators

```dart
void main() {
  String? text;

  // Using ?. null-aware operator
  int? length = text?.length;

  // Using ?? null coalescing operator
  String value = text ?? 'Unknown';

  // Using ??= null assignment
  text ??= 'Hello';

  print('Length: $length');
  print('Value: $value');
  print('Text: $text');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Length: null
Value: Unknown
Text: Hello
```

Uses null-aware operators (?., ??, ??=) for safe null handling.

- ?. calls a method only if object is not null.
- ?? provides default value if left side is null.
- ??= assigns only if variable is null.

**Best practices:**

- Use non-nullable types by default; only use ? when necessary.
- Always handle nullable types with null-aware operators.
- Use null coalescing operator (??) for default values.

**Common errors:**

- **Accessing property on nullable type**: Use ?. operator or check for null first.
- **Type is not nullable but assigned null**: Change type to nullable with ? or remove null assignment.

## Data Types

Dart's built-in data types including collections and commonly used types.

### Numbers

Working with int and double numeric types in Dart.

**Keywords:** numbers, int, double, arithmetic, operations

#### Integer operations

```dart
void main() {
  int a = 10;
  int b = 3;

  print('Addition: ${a + b}');
  print('Subtraction: ${a - b}');
  print('Multiplication: ${a * b}');
  print('Division: ${a / b}');
  print('Integer Division: ${a ~/ b}');
  print('Remainder: ${a % b}');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Addition: 13
Subtraction: 7
Multiplication: 30
Division: 3.3333333333333335
Integer Division: 3
Remainder: 1
```

Demonstrates various arithmetic operations on integers.

- ~/ performs integer division (floor division).
- % returns the remainder of division.

#### Double and arithmetic

```dart
void main() {
  double x = 10.5;
  double y = 3.2;

  print('Sum: ${x + y}');
  print('Product: ${x * y}');
  print('Power: ${x.pow(2)}');
  print('Absolute: ${(-5.5).abs()}');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Sum: 13.7
Product: 33.6
Power: 110.25000000000001
Absolute: 5.5
```

Shows operations on double type with decimal values.

- pow() method calculates power; requires import 'dart:math'.
- abs() returns absolute value.

**Best practices:**

- Use int for whole numbers and double for decimal numbers.
- Be aware of floating-point precision issues.
- Use integer division ~/ when whole number result is needed.

**Common errors:**

- **Precision issues with double arithmetic**: Use decimal package for precise calculations if needed.
- **Type mismatch between int and double**: Cast explicitly: double val = 5.toDouble().

### Strings

String manipulation, interpolation, and multi-line strings in Dart.

**Keywords:** strings, concatenation, interpolation, multi-line

#### String creation and interpolation

```dart
void main() {
  String firstName = 'John';
  String lastName = 'Doe';
  int age = 28;

  // String interpolation
  print('Full name: $firstName $lastName');
  print('Age: $age');
  print('Message: ${firstName.toUpperCase()} is $age years old');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Full name: John Doe
Age: 28
Message: JOHN is 28 years old
```

Demonstrates string interpolation with variables and expressions.

- Use $ for simple variables and ${expr} for complex expressions.
- String methods like toUpperCase() work on interpolations.

#### Multi-line strings

```dart
void main() {
  String poem = '''
  Roses are red,
  Violets are blue,
  Dart is awesome,
  And so are you!
  ''';

  print(poem);
  print('Length: ${poem.length}');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Roses are red,
Violets are blue,
Dart is awesome,
And so are you!
Length: 68
```

Uses triple quotes for multi-line strings preserving formatting.

- Triple quotes (''' or """) are used for multi-line strings.
- Preserves newlines and indentation.

#### String methods

```dart
void main() {
  String text = 'Dart Programming';

  print('Original: $text');
  print('Uppercase: ${text.toUpperCase()}');
  print('Lowercase: ${text.toLowerCase()}');
  print('Contains "Prog": ${text.contains("Prog")}');
  print('Index of "P": ${text.indexOf("P")}');
  print('Substring: ${text.substring(0, 4)}');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Original: Dart Programming
Uppercase: DART PROGRAMMING
Lowercase: dart programming
Contains "Prog": true
Index of "P": 5
Substring: Dart
```

Demonstrates common string manipulation methods.

- contains() checks if substring exists.
- indexOf() returns position of first match or -1.
- substring() extracts part of string.

**Best practices:**

- Use string interpolation instead of concatenation.
- Use raw strings (r'...') for regex patterns without escaping.
- Use triple quotes for text with multiple lines.

**Common errors:**

- **Missing curly braces in interpolation**: Use ${expression} for expressions; $ works for simple variables.

### Collections

Working with lists, maps, and sets in Dart.

**Keywords:** collections, list, map, set, array

#### Lists

```dart
void main() {
  List<int> numbers = [1, 2, 3, 4, 5];
  List<String> colors = ['red', 'green', 'blue'];

  print('Numbers: $numbers');
  print('First: ${numbers.first}');
  print('Last: ${numbers.last}');
  print('Length: ${numbers.length}');

  numbers.add(6);
  print('After add: $numbers');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Numbers: [1, 2, 3, 4, 5]
First: 1
Last: 5
Length: 5
After add: [1, 2, 3, 4, 5, 6]
```

Creates and manipulates lists with type parameters.

- Lists are ordered, mutable collections.
- Use List<Type> for typed lists.
- add() appends element to end of list.

#### Maps

```dart
void main() {
  Map<String, int> scores = {
    'Alice': 90,
    'Bob': 85,
    'Charlie': 92
  };

  print('Scores: $scores');
  print('Alice: ${scores['Alice']}');
  print('Keys: ${scores.keys}');
  print('Values: ${scores.values}');

  scores['David'] = 88;
  print('After add: $scores');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Scores: {Alice: 90, Bob: 85, Charlie: 92}
Alice: 90
Keys: (Alice, Bob, Charlie)
Values: (90, 85, 92)
After add: {Alice: 90, Bob: 85, Charlie: 92, David: 88}
```

Creates and manipulates maps with key-value pairs.

- Maps store key-value pairs where keys are unique.
- Use Map<KeyType, ValueType> for typed maps.

#### Sets and iteration

```dart
void main() {
  Set<String> languages = {'Dart', 'Java', 'Python'};

  print('Languages: $languages');
  print('Length: ${languages.length}');
  print('Contains Dart: ${languages.contains("Dart")}');

  languages.add('JavaScript');
  languages.add('Dart'); // Duplicate, ignored

  for (var lang in languages) {
    print('- $lang');
  }
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Languages: {Dart, Java, Python}
Length: 3
Contains Dart: true
- Dart
- Java
- Python
- JavaScript
```

Creates and manipulates sets (unordered, unique collections).

- Sets contain only unique elements.
- Duplicates are automatically ignored.

**Best practices:**

- Use the ok pattern for maps to check key existence.
- Remember collections are mutable by default.
- Use final for collections that won't be reassigned.

**Common errors:**

- **Accessing non-existent map key returns null**: Use containsKey() or ?. operator to check first.
- **Cannot modify unmodifiable collection**: Use List<int> instead of const if modification needed.

## Control Flow

Decision making and loop structures in Dart.

### Conditional Statements

If, else, and switch statements for decision making.

**Keywords:** if, else, switch, ternary, conditional

#### If and else statements

```dart
void main() {
  int age = 20;

  if (age < 13) {
    print('Child');
  } else if (age < 18) {
    print('Teenager');
  } else if (age < 65) {
    print('Adult');
  } else {
    print('Senior');
  }
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Adult
```

Demonstrates if-else if-else chain for multiple conditions.

- Use more specific conditions first in if-else chains.
- The last matching condition executes.

#### Ternary operator

```dart
void main() {
  int score = 75;
  String result = score >= 60 ? 'Pass' : 'Fail';

  print('Score: $score');
  print('Result: $result');

  String grade = score >= 90 ? 'A' :
                 score >= 80 ? 'B' :
                 score >= 70 ? 'C' : 'F';
  print('Grade: $grade');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Score: 75
Result: Pass
Grade: C
```

Uses ternary operator for short conditional assignments.

- Ternary operator: condition ? trueValue : falseValue
- Can chain ternary operators for multiple conditions.

#### Switch statement

```dart
void main() {
  String day = 'Monday';

  switch (day) {
    case 'Monday':
      print('Start of work week');
      break;
    case 'Friday':
      print('Almost weekend!');
      break;
    case 'Saturday':
    case 'Sunday':
      print('Weekend');
      break;
    default:
      print('Midweek');
  }
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Start of work week
```

Uses switch statement for multi-way branching on a single value.

- Use break to prevent fall-through to next case.
- Multiple cases can execute same code (case fallthrough).

**Best practices:**

- Use if-else for complex boolean logic.
- Use switch for single value against multiple options.
- Use ternary only for simple conditions.

**Common errors:**

- **Fall-through in switch without break**: Add break; at end of case block.
- **Missing default case**: Add default case to handle unexpected values.

### Loops

For, while, and do-while loops for iteration.

**Keywords:** loops, for, while, do-while, iteration

#### For loops

```dart
void main() {
  // Traditional for loop
  for (int i = 0; i < 5; i++) {
    print('Count: $i');
  }

  print('---');

  // For-in loop
  List<String> fruits = ['Apple', 'Banana', 'Cherry'];
  for (var fruit in fruits) {
    print('Fruit: $fruit');
  }
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Count: 0
Count: 1
Count: 2
Count: 3
Count: 4
---
Fruit: Apple
Fruit: Banana
Fruit: Cherry
```

Demonstrates traditional for loop and for-in loop over collections.

- Traditional for: for (init; condition; increment)
- For-in loop iterates over collections directly.

#### While and do-while loops

```dart
void main() {
  // While loop
  int count = 0;
  while (count < 3) {
    print('While: $count');
    count++;
  }

  print('---');

  // Do-while loop
  int num = 0;
  do {
    print('Do-while: $num');
    num++;
  } while (num < 3);
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
While: 0
While: 1
While: 2
---
Do-while: 0
Do-while: 1
Do-while: 2
```

Shows while loop (checks condition before) and do-while (checks after).

- While loop tests condition before executing body.
- Do-while loop executes body at least once.

#### Break and continue

```dart
void main() {
  // Break example
  for (int i = 0; i < 10; i++) {
    if (i == 5) break;
    print('Break loop: $i');
  }

  print('---');

  // Continue example
  for (int i = 0; i < 5; i++) {
    if (i == 2) continue;
    print('Continue loop: $i');
  }
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Break loop: 0
Break loop: 1
Break loop: 2
Break loop: 3
Break loop: 4
---
Continue loop: 0
Continue loop: 1
Continue loop: 3
Continue loop: 4
```

Uses break to exit loop early and continue to skip iteration.

- break exits the loop immediately.
- continue skips remaining code in current iteration.

**Best practices:**

- Use for loops with ranges when you know the iteration count.
- Use for-in for iterating over collections.
- Use while for condition-based loops.

**Common errors:**

- **Infinite loop**: Ensure loop condition will eventually be false.
- **Off-by-one errors**: Carefully check loop bounds and conditions.

## Functions & Methods

Declaring and using functions in Dart with parameters and return types.

### Function Basics

Function declaration, parameters, and return types.

**Keywords:** functions, methods, parameters, return, void

#### Basic function declaration

```dart
void greet(String name) {
  print('Hello, $name!');
}

int add(int a, int b) {
  return a + b;
}

void main() {
  greet('Alice');
  int result = add(5, 3);
  print('Sum: $result');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Hello, Alice!
Sum: 8
```

Demonstrates function declaration with parameters and return types.

- ReturnType functionName(parameters) { body }
- Use void for functions that don't return a value.

#### Optional and named parameters

```dart
void printInfo(String name, {int? age, String? city}) {
  print('Name: $name');
  if (age != null) print('Age: $age');
  if (city != null) print('City: $city');
}

void main() {
  printInfo('Alice');
  printInfo('Bob', age: 30);
  printInfo('Charlie', age: 25, city: 'NYC');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Name: Alice
Name: Bob
Age: 30
Name: Charlie
Age: 25
City: NYC
```

Uses named parameters in curly braces for flexible function calls.

- Named parameters are optional by default.
- Required named parameters use 'required' keyword.

#### Arrow functions and default values

```dart
int square(int x) => x * x;

void printMessage(String msg, {String prefix = 'INFO'}) {
  print('[$prefix] $msg');
}

void main() {
  print('Square of 5: ${square(5)}');

  printMessage('Application started');
  printMessage('Error occurred', prefix: 'ERROR');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Square of 5: 25
[INFO] Application started
[ERROR] Error occurred
```

Uses arrow syntax (=>) for concise function body and default parameter values.

- => syntax works only for single expressions.
- Default values provided with = in parameter list.

**Best practices:**

- Use descriptive function names that indicate what they do.
- Keep functions focused on a single responsibility.
- Use type annotations for clarity and type safety.

**Common errors:**

- **Missing return type**: Always specify return type or use void.
- **Parameter type mismatch on call**: Ensure argument types match parameter declarations.

### Advanced Functions

Anonymous functions, closures, and higher-order functions.

**Keywords:** anonymous functions, closures, higher-order functions, callbacks, lambda

#### Anonymous functions and callbacks

```dart
void main() {
  List<int> numbers = [1, 2, 3, 4, 5];

  // Anonymous function with forEach
  numbers.forEach((num) {
    print('Number: $num');
  });

  print('---');

  // Arrow syntax anonymous function
  List<int> squared = numbers.map((x) => x * x).toList();
  print('Squared: $squared');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Number: 1
Number: 2
Number: 3
Number: 4
Number: 5
---
Squared: [1, 4, 9, 16, 25]
```

Demonstrates anonymous functions used with collection methods.

- Anonymous functions are lambdas without explicit declaration.
- Use => for concise anonymous function bodies.

#### Closures

```dart
Function makeMultiplier(int factor) {
  return (int value) {
    return value * factor;
  };
}

void main() {
  var double = makeMultiplier(2);
  var triple = makeMultiplier(3);

  print('2 * 5 = ${double(5)}');
  print('3 * 5 = ${triple(5)}');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
2 * 5 = 10
3 * 5 = 15
```

Demonstrates closures that capture variables from outer scope.

- Closures capture variables from enclosing scope.
- Each closure maintains its own captured state.

**Best practices:**

- Use map(), filter(), reduce() for functional style code.
- Prefer closures over class methods when appropriate.
- Consider performance for nested anonymous functions.

**Common errors:**

- **Modified variable after closure created**: Closures capture by reference; be careful with mutable state.

## Object-Oriented Programming

Classes, objects, inheritance, and advanced OOP concepts in Dart.

### Classes & Objects

Defining classes, creating objects, and using constructors.

**Keywords:** classes, objects, constructors, properties, methods

#### Basic class definition

```dart
class Person {
  String name;
  int age;

  Person(this.name, this.age);

  void displayInfo() {
    print('Name: $name, Age: $age');
  }
}

void main() {
  var person = Person('Alice', 30);
  person.displayInfo();
  print('${person.name} is ${person.age} years old');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Name: Alice, Age: 30
Alice is 30 years old
```

Demonstrates class definition with properties, constructor, and methods.

- Constructor syntax: ClassName(parameters)
- Use this.property for automatic field assignment.

#### Multiple constructors

```dart
class Point {
  double x, y;

  Point(this.x, this.y);

  Point.origin() : x = 0, y = 0;

  Point.fromList(List<double> coords) : x = coords[0], y = coords[1];

  void display() => print('($x, $y)');
}

void main() {
  var p1 = Point(3, 4);
  var p2 = Point.origin();
  var p3 = Point.fromList([5, 6]);

  p1.display();
  p2.display();
  p3.display();
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
(3.0, 4.0)
(0.0, 0.0)
(5.0, 6.0)
```

Shows named constructors for different object initialization patterns.

- Named constructors use ClassName.constructorName syntax.
- Use: for initializer list before constructor body.

#### Getters and setters

```dart
class Rectangle {
  double width, height;

  Rectangle(this.width, this.height);

  double get area => width * height;

  set width(double w) {
    if (w > 0) width = w;
  }

  String get dimensions => '$width x $height';
}

void main() {
  var rect = Rectangle(5, 3);
  print('Area: ${rect.area}');
  print('Dimensions: ${rect.dimensions}');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Area: 15.0
Dimensions: 5.0 x 3.0
```

Uses getters and setters for computed properties and controlled access.

- Getters compute values on-the-fly.
- Setters allow controlled property assignment.

**Best practices:**

- Use meaningful class and property names.
- Keep methods focused on single responsibility.
- Use getters/setters instead of public fields when behavior needed.

**Common errors:**

- **Accessing undefined property**: Ensure property is declared in class.
- **Constructor parameter not assigned to field**: Use this.fieldName or explicit assignment.

### Inheritance & Polymorphism

Extending classes, method overriding, and polymorphic behavior.

**Keywords:** inheritance, extends, override, super, polymorphism

#### Class inheritance and super

```dart
class Animal {
  String name;

  Animal(this.name);

  void makeSound() {
    print('$name makes a sound');
  }
}

class Dog extends Animal {
  Dog(String name) : super(name);

  @override
  void makeSound() {
    print('$name barks');
  }
}

void main() {
  var dog = Dog('Rex');
  dog.makeSound();
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Rex barks
```

Demonstrates inheritance with extends and method overriding.

- Use extends to inherit from a class.
- Use super() to call parent constructor.
- Use @override annotation when overriding methods.

#### Abstract classes and interfaces

```dart
abstract class Shape {
  double get area;
  void display();
}

class Circle implements Shape {
  double radius;

  Circle(this.radius);

  @override
  double get area => 3.14159 * radius * radius;

  @override
  void display() => print('Circle with radius $radius, area: ${area.toStringAsFixed(2)}');
}

void main() {
  var circle = Circle(5);
  circle.display();
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Circle with radius 5, area: 78.54
```

Uses abstract classes and implements contracts for polymorphism.

- Abstract classes define contract with unimplemented methods.
- implements keyword creates interface implementation contract.

**Best practices:**

- Use meaningful inheritance hierarchies.
- Prefer composition over inheritance when possible.
- Use abstract classes to define contracts.

**Common errors:**

- **Cannot instantiate abstract class**: Either implement abstract methods or use concrete subclass.
- **Method signature mismatch in override**: Ensure overridden method has compatible signature.

## Async Programming

Futures, async/await, and streams for asynchronous operations.

### Futures & Promises

Working with Future objects for asynchronous operations.

**Keywords:** futures, async, promises, then, callbacks

#### Creating and handling futures

```dart
Future<String> fetchData() {
  return Future.delayed(Duration(seconds: 1), () {
    return 'Data loaded';
  });
}

void main() {
  print('Fetching data...');

  fetchData().then((data) {
    print('Result: $data');
  }).catchError((error) {
    print('Error: $error');
  });

  print('Request sent');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Fetching data...
Request sent
Result: Data loaded
```

Demonstrates Future creation and handling with then/catchError.

- Future represents a value that will be available later.
- then() executes when Future completes successfully.
- catchError() handles exceptions in Future.

#### Future.wait and multiple futures

```dart
Future<int> calculateSum(int a, int b) {
  return Future.delayed(Duration(milliseconds: 500), () => a + b);
}

void main() async {
  print('Starting calculations...');

  var result = await Future.wait([
    calculateSum(5, 3),
    calculateSum(10, 2),
    calculateSum(7, 4)
  ]);

  print('Results: $result');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Results: [8, 12, 11]
```

Uses Future.wait to handle multiple concurrent futures.

- Future.wait waits for all futures to complete.
- Returns list of results in same order as inputs.

**Best practices:**

- Use async/await instead of chains of then().
- Always handle errors in futures.
- Use Future.wait for parallel operations.

**Common errors:**

- **Uncaught exceptions in futures**: Always add catchError() or await in try-catch.
- **Blocking on async operations**: Use await in async functions, not synchronous code.

### Async/Await

Using async/await syntax for cleaner asynchronous code.

**Keywords:** async, await, asynchronous, try-catch

#### Basic async/await

```dart
Future<int> fetchNumber() {
  return Future.delayed(Duration(seconds: 1), () => 42);
}

void main() async {
  print('Fetching number...');

  int number = await fetchNumber();
  print('Number: $number');

  int doubled = number * 2;
  print('Doubled: $doubled');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Fetching number...
Number: 42
Doubled: 84
```

Demonstrates async function with await for sequential async operations.

- await pauses execution until Future completes.
- await can only be used in async functions.

#### Error handling with try-catch

```dart
Future<String> riskyOperation(bool shouldFail) {
  return Future.delayed(Duration(milliseconds: 500), () {
    if (shouldFail) {
      throw Exception('Operation failed');
    }
    return 'Success';
  });
}

void main() async {
  try {
    var result = await riskyOperation(false);
    print('Result: $result');

    await riskyOperation(true);
  } catch (e) {
    print('Error caught: $e');
  } finally {
    print('Operation completed');
  }
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Result: Success
Error caught: Exception: Operation failed
Operation completed
```

Uses try-catch-finally for robust async error handling.

- try-catch works with await for async exceptions.
- finally block always executes regardless of success or error.

**Best practices:**

- Use async/await instead of Future.then() chains.
- Always wrap await calls in try-catch when errors expected.
- Use finally for cleanup operations.

**Common errors:**

- **Await outside async function**: Add async keyword to function signature.
- **Unhandled exceptions in async functions**: Add try-catch around await expressions.

## Advanced Features

Generics, extensions, pattern matching, and advanced language features.

### Generics

Creating reusable generic classes and methods.

**Keywords:** generics, type parameters, templates, bounded types

#### Generic classes and methods

```dart
class Stack<T> {
  final List<T> items = [];

  void push(T value) => items.add(value);
  T pop() => items.removeLast();
  bool get isEmpty => items.isEmpty;
}

void main() {
  var intStack = Stack<int>();
  intStack.push(1);
  intStack.push(2);
  print('Popped: ${intStack.pop()}');

  var stringStack = Stack<String>();
  stringStack.push('Hello');
  stringStack.push('World');
  print('Popped: ${stringStack.pop()}');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Popped: 2
Popped: World
```

Implements generic Stack class that works with any type.

- Use <T> as type parameter placeholder.
- Specify concrete type when instantiating: Stack<int>().

#### Bounded generic types

```dart
class Comparable<T extends num> {
  T value;

  Comparable(this.value);

  bool isGreaterThan(T other) => value > other;

  T getDouble() => (value * 2) as T;
}

void main() {
  var intComp = Comparable<int>(10);
  print('10 > 5? ${intComp.isGreaterThan(5)}');

  var doubleComp = Comparable<double>(3.5);
  print('3.5 > 2.0? ${doubleComp.isGreaterThan(2.0)}');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
10 > 5? true
3.5 > 2.0? true
```

Demonstrates bounded generics restricting type parameter to subtype.

- Use extends to bound type parameter to specific type.
- Allows using methods specific to bound type.

**Best practices:**

- Use generics to create reusable, type-safe code.
- Bound generics when methods require specific capabilities.
- Avoid using dynamic when generics can provide type safety.

**Common errors:**

- **Type mismatch with generic**: Ensure actual type matches declared type parameter.

### Extensions & Error Handling

Extension methods, custom exceptions, and error handling patterns.

**Keywords:** extensions, custom exceptions, error handling, try-catch

#### Extension methods

```dart
extension StringExtensions on String {
  bool get isEmail => contains('@');

  String capitalize() {
    if (isEmpty) return this;
    return this[0].toUpperCase() + substring(1);
  }
}

void main() {
  String text = 'hello world';
  print('Capitalized: ${text.capitalize()}');

  String email = 'user@example.com';
  print('Is email: ${email.isEmail}');
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Capitalized: Hello world
Is email: true
```

Demonstrates extension methods adding functionality to existing types.

- Extensions add methods to classes without inheritance.
- Can add getters, setters, and methods.

#### Custom exceptions and error handling

```dart
class InvalidAgeException implements Exception {
  String message;
  InvalidAgeException(this.message);

  @override
  String toString() => message;
}

void validateAge(int age) {
  if (age < 0 || age > 150) {
    throw InvalidAgeException('Age must be between 0 and 150');
  }
}

void main() {
  try {
    validateAge(25);
    print('Age is valid');

    validateAge(-5);
  } on InvalidAgeException catch (e) {
    print('Error: $e');
  } catch (e) {
    print('Unexpected error: $e');
  }
}
```

_exec_
```dart
dart main.dart
```

_output_
```dart
Age is valid
Error: Age must be between 0 and 150
```

Defines custom exception and handles specific exception types.

- Implement Exception interface for custom exceptions.
- Use on clausefor specific exception catching.

**Best practices:**

- Create extension methods for common operations.
- Create specific exception types for different error conditions.
- Use on clause to handle specific exceptions differently.

**Common errors:**

- **Uncaught exception type**: Add on clause for specific exception before generic catch.
- **Extension method not found**: Ensure extension is imported or defined in scope.
