Dart Syntax and Basic Concepts

Delve into the foundational concepts of Dart programming with this comprehensive guide. Covering essential topics like syntax, variable types, functions, loops, and control flow, the article offers a thorough understanding of Dart basics. Ideal for beginners, it lays the groundwork for mastering Dart, from simple data types to complex functions, ensuring a strong foundation in this versatile and powerful programming language.

Dec 28, 2023

Introduction

Welcome to the world of Dart, a modern language designed for ease of use and high performance. Whether you're aiming to develop mobile apps with Flutter or looking to explore web and server-side development, learning Dart is your first step. In this article, we'll dive into the basic syntax and fundamental concepts of Dart, setting a strong foundation for your coding journey.

Basic Syntax

Hello World in Dart
Every programming journey often begins with a 'Hello World' program. Here's what it looks like in Dart:
void main() { print('Hello, World!'); }
This program defines a main function, which is the entry point of every Dart application. The print function outputs the string 'Hello, World!' to the console.
Variables and Data Types
  1. Basic Declaration and Initialization
    1. In Dart, variables can be declared using either explicit type annotations or the var keyword for type inference.
      • Type Annotation:
        • String name = 'Alice'; int age = 30;
      • Type Inference with var:
        • var city = 'New York'; // Inferred as String var distance = 100; // Inferred as int
  1. Final, Const, and Late
    1. Dart provides final, const, and late keywords for special variable declarations.
      • final: For values that are set once and are immutable.
        • final String greeting = 'Hello';
      • const: Declares compile-time constants.
        • const double pi = 3.14159;
          ๐Ÿ’ก
          In dart there is no convention of using UPPERCASE letters when using constant variable. Instead dart uses k letter at the beginning of variable name.
          ex:
          kAnimationDuration = Default Animation Duration in Flutter
          ย 
      • late: Indicates delayed initialization.
        • late String description; // can be reassigned late final int calculatedValue; // once set vaue late String? nullOrStringValue; // must be either null or String value.
          ๐Ÿšง
          Using late keyword is risky, if variable does not assigned(even itโ€™s nullable - String?) and being used, dart throws compile-time error.
          ย 
      Code examples
      late String description; late String? nullableDescription; late dynamic dynamicValue; late var lateVariable; late final String finalVariable; late final String? nullableFinalVariable; ///! Error late variable must be initialized before use // print(description); // print(nullableDescription); description = 'Hello'; print(description); //* OK => prints Hello nullableDescription = null; print(nullableDescription); //* OK => prints null nullableDescription = 'Hello'; print(nullableDescription); //* OK => prints Hello dynamicValue = 'Hello'; print(dynamicValue); //* OK => prints Hello dynamicValue = 1; print(dynamicValue); //* OK => prints 1 dynamicValue = null; print(dynamicValue); //* OK => prints null lateVariable = 'Hello'; print(lateVariable); //* OK => prints Hello lateVariable = 2; //* OK print(lateVariable); //* OK => prints 2 finalVariable = 'Hello'; print(finalVariable); //* OK => prints Hello // finalVariable = 2; //! Error => The final variable 'finalVariable' can only be set once. nullableFinalVariable = null; print(nullableFinalVariable); //* OK => prints null // nullableFinalVariable = 'Hello'; //! Error => The final variable 'nullableFinalVariable' can only be set once.
  1. Dynamic vs Var
    1. Dart offers two dynamic types: dynamic and var. The difference lies in type checking:
      • dynamic: Explicitly disables static type checking. The type can change over time.
        • dynamic variable = 'Hello'; variable = 100; // Allowed
      • var: Maintains static type checking. Once set, the type cannot change.
        • var variable = 'Hello'; // variable = 100; // Error: type 'int' is not assignable to type 'String'

Dart's Data Types

  1. Numbers
      • int: Represents integers.
        • int population = 150000;
      • double: Handles floating-point numbers.
        • double price = 99.99;
  1. Strings
    1. Strings in Dart are sequences of UTF-16 code units.
      String fullName = 'John Doe'; String multiline = ''' This is a multiline string. ''';
      String interpolation:
      String greeting = "Hello, $fullName!"; String greeting = "Hello, ${getFullName()}"; String getFullName() => "YourName";
  1. Booleans
    1. The bool type represents Boolean values of true or false.
      bool isVisible = false; bool isEligible = age > 18;
  1. Lists, Maps and Sets
      • List: A collection of ordered objects. Dart infers the Listโ€™s type if not explicitly declared.
        • List<String> languages = ['Dart', 'JavaScript', 'Python']; var numbers = [1, 2, 3, 4, 5]; // Inferred as List<int>
      • Map: Key-value pairs collection.
        • Map<String, String> capitals = { 'USA': 'Washington D.C.', 'Japan': 'Tokyo', };
      • Set: A collection of unordered, unique objects.
        • Set<int> numbers= {1, 2, 3, 4, 5}; var numbers2 = {1, 2, 3, 4, 5}; // Inferred as Set<int>
      ๐Ÿ’ก
      Dart also supports popular collection types like: Queue, Stack, LinkedList, Tuple etc
  1. Runes and Symbols
      • Runes: For representing Unicode characters in Dart.
        • Runes input = new Runes('\u{1F605}'); print(new String.fromCharCodes(input)); // ๐Ÿ˜…
      • Symbols: Represent operators or identifiers used in Dartโ€™s reflection capabilities.
  1. Null Safety
    1. Dart 2.12 introduced null safety, making all variables non-nullable by default.
      • Nullable types with ?:
        • int? nullableAge;
      • Null-aware operators (?., ??, ??=):
        • int? age; print(age?.isEven); // Use ?. for safe access // same as if(age != null) { print(age.isEven) // prints boolean value } else { print(age) // prints null } print(age ?? 0); // Default value if null // same as if(age != null) { print(age); // age value } else { print(0); } age ??= 10; // Assign value if null // same as if(age !=null) {} else { age = 10; }
          ย 

Loops in Dart.

  1. For Loop
      • Standard For Loop: Iterates a set number of times.
        • for (int i = 0; i < 10; i++) { print('Iteration $i'); // prints 0 ~ 9 }
      • For-In Loop: Iterates over elements in a collection.
        • var numbers = [1, 2, 3, 4, 5]; // Inferred as List<int> for (var number in numbers) { print('Number: $number'); }
  1. While Loop
      • Executes as long as the condition is true.
        • int count = 0; while (count < 5) { print('Count is $count'); count++; } // prints 0 ~ 4
  1. Do-While Loop
      • Executes the block once before checking the condition.
        • int counter = 0; do { print('Counter is $counter'); counter++; } while (counter < 5);
  1. Break and Continue
      • Break: Exits the loop immediately.
        • for (int i = 0; i < 10; i++) { if (i == 5) break; // Exits the loop when i is 5 print(i); }
      • Continue: Skips the rest of the current loop iteration.
        • dartCopy code for (int i = 0; i < 10; i++) { if (i % 2 == 0) continue; // Skips even numbers print('Odd: $i'); }

Logical Blocks

  1. Simple If Statement
      • Executes code block if the condition is true.
        • int age = 20; if (age >= 18) { print('Adult'); }
  1. If-Else Statement
      • Provides an alternative path if the if condition is false.
        • if (age >= 18) { print('Adult'); } else { print('Minor'); }
  1. If-Else-If Ladder
      • Multiple conditions checked in sequence.
        • if (age >= 18) { print('Adult'); } else if (age >= 13) { print('Teenager'); } else { print('Child'); }
  1. Nested If Statements
      • If statements within other if statements.
        • bool hasDrivingLicense = true; if (age >= 18) { if (hasDrivingLicense) { print('Can drive'); } else { print('Cannot drive without a license'); } }
  1. Conditional (Ternary) Operator
      • A concise way to write simple if-else statements.
        • String type = age >= 18 ? 'Adult' : 'Minor';
  1. Switch Case
      • Used for selecting one of many code blocks to be executed.
        • String grade = 'A'; switch (grade) { case 'A': print('Excellent'); break; case 'B': print('Good'); break; default: print('Invalid grade'); }

Defining Functions

  1. Basic Function Syntax
      • A simple function declaration includes the return type, function name, parameters, and the body.
        • void greet(String name) { print('Hello, $name!'); }
  1. Return Types
      • Functions can return values. The return type is specified before the function name.
        • int add(int a, int b) { return a + b; }
      • If a function does not return a value, its return type is void.
  1. Optional Parameters
      • Dart supports optional positional and named parameters.
        • Positional: Enclosed in square brackets [].
          • void sayMessage(String message, [String? author]) { print('$message by ${author ?? 'Anonymous'}'); }
        • Named: Enclosed in curly braces {} and often used with default values.
          • void setSettings({ bool bold = false, bool hidden = false }) { // Function body }
  1. Arrow Functions
      • Suitable for single-expression functions.
        • void greet(String name) => print('Hello, $name!');
  1. Anonymous Functions
      • Often used in collections or as arguments to higher-order functions.
        • var numbers = [1, 2, 3]; numbers.forEach((number) { print(number); });

Advanced Function Concepts

  1. Higher-Order Functions
      • Functions that can accept other functions as parameters or return a function.
        • void executeFunction(Function callback) { callback(); }
  1. Function as First-Class Objects
      • Functions can be assigned to variables and passed as parameters.
        • var multiply = (int a, int b) => a * b; int result = multiply(10, 2);
  1. Closures
      • Functions that can access and modify variables from their lexical scope.
        • Function makeAdder(int addBy) { return (int i) => addBy + i; } var adder = makeAdder(5); print(adder(3)); // Outputs 8
  1. Generators
      • Functions that produce sequences of values using yield and yield*.
        • Iterable<int> count(int max) sync* { for (int i = 0; i < max; i++) { yield i; } }
  1. Async Functions
      • Functions that handle asynchronous operations, returning Future or Stream.
        • Future<void> fetchData() async { // Asynchronous operations }
  1. Extension Methods
      • Allows adding new functionalities to existing classes.
        • extension StringExtension on String { bool get isCapitalized => this.length > 0 && this[0].toUpperCase() == this[0]; }

Function Parameters and Default Values

  1. Default Parameter Values
      • Set default values for parameters, both positional and named.
        • void printMessage(String message, {int times = 1}) { for (int i = 0; i < times; i++) { print(message); } }
  1. Required Named Parameters
      • Making a named parameter required using required keyword.
        • void setAddress({required String street, String? city}) { // Function body }

Conclusion

This overview introduces you to the very basics of Dart programming. You've seen how to write a simple Dart program, declare variables, use control flow statements, define functions, and handle errors. As you progress, these concepts will be the building blocks for more complex and exciting Dart applications.
Stay tuned for our next article where we delve deeper into the world of Dart!
ย 
ย