## Learning Objectives

By the end of this chapter, you will be able to:

- Understand Dart's type system and common data types
- Declare variables using explicit types and `var`/`final`/`const`
- Use arithmetic, comparison, and logical operators
- Perform basic input and output (console) for small programs
- Practice writing small utility functions that use these basics

1

## Why Dart First

Dart is the language behind Flutter. It is statically typed with type inference, supports sound null safety, and mixes imperative, object-oriented, and functional styles. Mastering basic types and operators makes reading Flutter examples and building app logic straightforward.

Understanding Dart fundamentals is essential because every Flutter widget, every state management pattern, and every piece of business logic you write will use Dart syntax and concepts. The language's design emphasizes clarity, safety, and developer productivity.

2

## Basic Data Types and Declarations

Dart provides several built-in data types and multiple ways to declare variables. Understanding these is fundamental to writing effective Dart code.

#### `int`

Whole numbers (e.g., 0, 42, -7)

#### `double`

Floating-point numbers (e.g., 3.14)

#### `String`

Text (e.g., "Afrilen")

#### `bool`

Boolean values: true/false

#### `List<T>`

Ordered collection (e.g., `List<int>`)

#### `Map<K, V>`

Key/value pairs (e.g., `Map<String, dynamic>`)

#### `dynamic`

Runtime-typed value (use sparingly)

### Variable Declaration Keywords

#### `var`

Compiler infers the type at assignment time. Use when the type is obvious from the value.

#### `final`

Single-assignment variable (value set once). Use when a value won't change after construction but may be computed at runtime.

#### `const`

Compile-time constant (immutable and canonicalized). Use for values known at compile time (literals, const constructors).

### Code Pattern: Declaration Examples

    int count = 10;
    double price = 9.99;
    String title = 'Mobile Development';
    bool isOpen = true;

    var name = 'Adu';        // inferred as String
    final createdAt = DateTime.now(); // runtime constant
    const maxLimit = 100;    // compile-time constant

#### Best Practices:

- Use `final` when a value won't change after construction but may be computed at runtime.
- Use `const` for values known at compile time (literals, const constructors).
- Prefer explicit types in public APIs for clarity.

3

## Null Safety Basics

Dart's null safety feature helps prevent null reference errors, which are a common source of bugs in many programming languages. Understanding null safety is crucial for writing robust Dart code.

#### Non-nullable by Default

By default, types are non-nullable (e.g., `String name` cannot be null). This prevents many common null reference errors.

#### Nullable Types

Use nullable types with `?` (e.g., `String? nickname`) when a value might be null.

#### Null Assertion Operator

Use the null assertion operator `!` to assert non-null (use sparingly and only when you're certain the value is not null).

#### Null Coalescing

Use `??` to provide default values when a nullable variable might be null.

### Examples

    String? nickname;          // can be null
    var displayName = nickname ?? 'Guest'; // default to 'Guest'
    print(displayName);

4

## Strings and Interpolation

Dart provides powerful string manipulation capabilities. You can concatenate strings or use string interpolation for more readable code.

#### Concatenation

Use the `+` operator to concatenate strings:

    String greeting = 'Hello' + ' ' + 'World';

#### String Interpolation

Use `${expression}` or `$variable` for interpolation (preferred method):

    String first = 'Adu';
    String last = 'Amankwah';
    String full = '$first $last';        // interpolation
    print('Welcome, $full');

Note: String interpolation is generally preferred over concatenation as it's more readable and efficient.

5

## Collections: List and Map

Collections are essential data structures in Dart. Lists store ordered sequences of items, while Maps store key-value pairs.

### List

Lists are ordered collections of items. You can create them using list literals or typed constructors:

    // List literal
    var nums = [1, 2, 3];

    // Typed variant
    List<String> names = [];

    // Accessing elements
    print(nums[0]);            // first element (index 0)

### Map

Maps store key-value pairs. They're useful for representing structured data:

    // Map literal
    var person = {'name': 'Adu', 'age': 22};

    // Typed variant
    Map<String, dynamic> item = {};

    // Accessing values
    print(person['name']);     // value by key

6

## Operators

Dart provides a comprehensive set of operators for performing various operations on values.

### Arithmetic Operators

Basic mathematical operations:

- `+` - Addition
- `-` - Subtraction
- `*` - Multiplication
- `/` - Division (returns double)
- `~/` - Integer division
- `%` - Modulus (remainder)

    int a = 7;
    int b = 3;
    print(a + b);   // 10
    print(a / b);   // 2.3333333333
    print(a ~/ b);  // 2 (integer division)
    print(a % b);   // 1 (remainder)

### Comparison Operators

These operators return `bool` values:

- `==` - Equal to
- `!=` - Not equal to
- `>` - Greater than
- `<` - Less than
- `>=` - Greater than or equal to
- `<=` - Less than or equal to

### Logical Operators

- `&&` - Logical AND (both conditions must be true)
- `||` - Logical OR (at least one condition must be true)
- `!` - Logical NOT (negates a boolean value)

### Assignment and Compound Operators

- `=` - Assignment
- `+=` - Add and assign
- `-=` - Subtract and assign
- `*=` - Multiply and assign
- `/=` - Divide and assign
- `??=` - Assign if null

### Example with Logic

    bool hasAccess = (age >= 18) && isOpen;

7

## Basic I/O in Dart (Console Programs)

Dart console I/O uses `dart:io`. For beginner exercises and quick utilities, use `stdin.readLineSync()` to read user input.

### Example: Read and Print

    import 'dart:io';

    void main() {
      stdout.write('Enter your name: ');
      String? name = stdin.readLineSync();
      print('Hello, ${name ?? 'Guest'}!');
    }

#### Important Notes:

- `stdin.readLineSync()` returns `String?`; always handle null safely.
- `stdout.write()` doesn't add a newline; `print()` does.
- Use the null coalescing operator `??` to provide default values.

8

## Example Utility: Rectangle Area (Step-by-Step)

Goal: Prompt user for width and height, compute area, display result.

### Example Code

    import 'dart:io';

    void main() {
      stdout.write('Enter width: ');
      String? w = stdin.readLineSync();
      stdout.write('Enter height: ');
      String? h = stdin.readLineSync();

      // Parse inputs safely
      double width = double.tryParse(w ?? '') ?? 0.0;
      double height = double.tryParse(h ?? '') ?? 0.0;

      double area = width * height;
      print('Area: $area');
    }

#### Key Points:

- Use `double.tryParse()` to avoid exceptions and provide a fallback value.
- Always validate input and inform the user if values are invalid (exercise extension).
- Handle null values from `stdin.readLineSync()` using the null coalescing operator.

9

## Small Functions and Modularity

Wrap logic in functions so code is testable and reusable. Functions allow you to break down complex problems into smaller, manageable pieces.

### Pattern

    double calculateArea(double w, double h) => w * h;

    void main() {
      // get inputs...
      double area = calculateArea(width, height);
      print('Area: $area');
    }

Benefits of Functions:

- Reusability: Write once, use multiple times
- Testability: Test functions independently
- Readability: Code becomes more self-documenting
- Maintainability: Changes in one place affect all usages

10

## Common Pitfalls and Best Practices

Avoiding common mistakes will make your Dart code more robust and maintainable.

#### Null Safety

Don't assume `stdin.readLineSync()` returns non-null; always handle nullable results using the null coalescing operator or null checks.

#### Variable Mutability

Prefer `final` for variables that shouldn't change. This makes your intent clear and prevents accidental modifications.

#### Avoid Dynamic Types

Avoid `dynamic` unless necessary; prefer typed `Map<String, dynamic>` when parsing JSON to maintain type safety.

#### Input Validation

Always validate numeric parsing and provide clear error messages to users when input is invalid.