Md Mominul Islam | Software and Data Enginnering | SQL Server, .NET, Power BI, Azure Blog

while(!(succeed=try()));

LinkedIn Portfolio Banner

Latest

Home Top Ad

Responsive Ads Here

Post Top Ad

Responsive Ads Here

Tuesday, August 26, 2025

Master Flutter & Dart Course - Module 2: Dart Programming Fundamentals: From Beginner Basics to Advanced Mastery





Table of Contents

  1. Introduction to Dart Programming Fundamentals
    • 1.1 Why Learn Dart for Flutter Development?
    • 1.2 Overview of Chapter Objectives and Learning Outcomes
    • 1.3 Setting Up Your Dart Environment: Step-by-Step Guide
  2. Dart Syntax, Variables, and Data Types
    • 2.1 Basic Dart Syntax Rules: Getting Started with Hello World
    • 2.2 Variables in Dart: Declaration, Initialization, and Naming Conventions
    • 2.3 Primitive Data Types: Numbers, Strings, Booleans, and More
    • 2.4 Advanced Data Types: Lists, Maps, Sets, and Runes
    • 2.5 Type Inference with 'var', 'dynamic', and 'final/const'
    • 2.6 Real-Life Examples: Managing User Profiles in a Social App
    • 2.7 Best Practices, Exception Handling, Pros/Cons, and Alternatives
  3. Control Structures: Conditionals and Loops
    • 3.1 Conditional Statements: if, if-else, else-if Ladders, and Ternary Operators
    • 3.2 Switch-Case Statements for Multi-Way Branching
    • 3.3 Loops: for, while, do-while, and for-in Iterations
    • 3.4 Break, Continue, and Nested Loops
    • 3.5 Real-Life Examples: Inventory Management System in an E-Commerce App
    • 3.6 Best Practices, Exception Handling, Pros/Cons, and Alternatives
  4. Functions, Parameters, and Return Types
    • 4.1 Defining and Calling Functions: Basics and Syntax
    • 4.2 Parameters: Positional, Named, Optional, and Default Values
    • 4.3 Return Types: Void, Single Values, and Multiple Returns via Tuples
    • 4.4 Arrow Functions and Anonymous Functions
    • 4.5 Higher-Order Functions and Closures
    • 4.6 Real-Life Examples: Processing Orders in a Food Delivery App
    • 4.7 Best Practices, Exception Handling, Pros/Cons, and Alternatives
  5. Object-Oriented Programming in Dart: Classes, Objects, and Inheritance
    • 5.1 Classes and Objects: Constructors, Properties, and Methods
    • 5.2 Inheritance: Single, Multi-Level, and Hierarchical
    • 5.3 Overriding Methods and Using 'super'
    • 5.4 Abstract Classes, Interfaces, and Mixins
    • 5.5 Encapsulation, Polymorphism, and Abstraction in Practice
    • 5.6 Real-Life Examples: Building a Vehicle Rental System
    • 5.7 Best Practices, Exception Handling, Pros/Cons, and Alternatives
  6. Asynchronous Programming: Futures, Async, and Await
    • 6.1 Understanding Synchronous vs. Asynchronous Code
    • 6.2 Futures: Creating, Chaining, and Handling Errors
    • 6.3 Async and Await Keywords for Readable Async Code
    • 6.4 Streams for Continuous Data Flows
    • 6.5 Isolates for Concurrency in Dart
    • 6.6 Real-Life Examples: Fetching Weather Data in a Mobile App
    • 6.7 Best Practices, Exception Handling, Pros/Cons, and Alternatives
  7. Practical Exercise: Building a Simple Dart Calculator Program
    • 7.1 Step-by-Step Project Setup
    • 7.2 Implementing Basic Operations: Addition, Subtraction, Multiplication, Division
    • 7.3 Adding Advanced Features: Error Handling, User Input Validation, and History Logging
    • 7.4 Real-Life Integration: Extending to a Budget Tracker App
    • 7.5 Testing and Debugging Your Calculator
  8. Conclusion and Next Steps
    • 8.1 Recap of Key Learning Outcomes
    • 8.2 Tips for Advancing Your Dart Skills
    • 8.3 Preview of Upcoming Chapters in the Master Flutter & Dart Course

1. Introduction to Dart Programming Fundamentals

1.1 Why Learn Dart for Flutter Development?

Dart is the programming language powering Flutter, Google's UI toolkit for building natively compiled applications for mobile, web, and desktop from a single codebase. As a beginner stepping into mobile app development, understanding Dart is crucial because it forms the backbone of Flutter widgets, state management, and app logic. Imagine building a house without knowing how to use bricks—Dart is those bricks for Flutter.

In real life, Dart's design makes it ideal for apps that need high performance and smooth user experiences, like banking apps where quick calculations and responsive interfaces are key. For instance, apps like Alibaba and Hamilton use Flutter with Dart to handle millions of users seamlessly. Learning Dart not only equips you for Flutter but also introduces concepts transferable to other languages like JavaScript or Java.

From a beginner's perspective, Dart is user-friendly with its clean syntax, which resembles JavaScript but with stronger typing for fewer bugs. For advanced users, its just-in-time (JIT) compilation during development and ahead-of-time (AOT) for production ensure fast execution. Pros of Dart include strong null safety (introduced in Dart 2.12), which prevents null pointer exceptions—a common pain in other languages. Cons? It's less widespread outside Flutter ecosystems, so community resources might be Flutter-focused. Alternatives like Kotlin for Android or Swift for iOS exist, but Dart's cross-platform nature wins for multi-platform apps.

Best practice: Always enable null safety in your projects with --dart-define=environment=null-safety to catch errors early.

1.2 Overview of Chapter Objectives and Learning Outcomes

This chapter dives deep into Dart's core concepts to build a solid foundation. We'll cover syntax basics, control flows, functions, OOP, and async programming—everything step-by-step with code snippets.

By the end, you'll be able to:

  • Write basic Dart programs with proper syntax.
  • Understand asynchronous programming for app responsiveness.
  • Apply these in real-world scenarios, like data processing in apps.

We'll use real-life examples, such as managing e-commerce inventories or fetching API data, to make learning engaging and practical.

1.3 Setting Up Your Dart Environment: Step-by-Step Guide

To start coding in Dart, follow this easy setup:

  1. Download Dart SDK: Visit the official Dart website (dart.dev) and download the SDK for your OS (Windows, macOS, Linux). It's free and lightweight.
  2. Install via Package Manager:
    • On macOS: Use Homebrew with brew tap dart-lang/dart then brew install dart.
    • On Windows: Use Chocolatey with choco install dart-sdk.
    • On Linux: sudo apt-get install dart.
  3. Verify Installation: Open a terminal and run dart --version. You should see something like "Dart SDK version: 3.1.0 (stable)".
  4. Set Up an IDE: Use VS Code with the Dart extension for syntax highlighting and debugging. Alternatively, Android Studio or IntelliJ for Flutter integration.
  5. Create Your First Project: Run dart create my_first_app to generate a sample project. Navigate to it and run dart run to execute.

Real-life tip: In a team setting, use pub (Dart's package manager) to manage dependencies. For example, dart pub add http for network requests.

Exception handling during setup: If dart command not found, add the SDK's bin folder to your PATH environment variable. Pros of this setup: Quick and cross-platform. Cons: Manual updates needed. Alternative: Use Flutter SDK, which bundles Dart.

Now, let's jump into the core topics.

2. Dart Syntax, Variables, and Data Types

Dart's syntax is straightforward, making it accessible for beginners while powerful for advanced use. We'll start with basics and build up to complex data handling.

2.1 Basic Dart Syntax Rules: Getting Started with Hello World

Dart programs start with a main() function, the entry point. Comments use // for single-line or /* */ for multi-line. Semicolons end statements.

Here's a beginner's Hello World:

dart
void main() {
print('Hello, World!'); // Outputs to console
}

Run this with dart run hello.dart. In real life, this is like printing a welcome message in a chat app.

Advanced: Use string interpolation for dynamic output: print('Hello, $name!');.

Best practice: Use consistent indentation (2 spaces) for readability.

2.2 Variables in Dart: Declaration, Initialization, and Naming Conventions

Variables store data. Declare with type or use inference.

Basic example:

dart
String name = 'Alice'; // Explicit type
var age = 25; // Inferred as int

Naming: Use camelCase for variables, e.g., userScore. Avoid starting with numbers.

Real-life: In a fitness app, double weight = 70.5; tracks user weight.

Exception handling: Dart throws errors for uninitialized variables in null-safe mode. Use late for lazy initialization: late String description;.

Pros: Strong typing reduces runtime errors. Cons: More verbose than dynamic languages like Python. Alternative: JavaScript's let for similar inference.

2.3 Primitive Data Types: Numbers, Strings, Booleans, and More

Dart primitives include:

  • int: Whole numbers, e.g., int score = 100;.
  • double: Floating points, e.g., double pi = 3.14;.
  • String: Text, supports multi-line with triple quotes: String message = '''Hello\nWorld''';.
  • bool: True/false, e.g., bool isActive = true;.
  • num: Super type for int/double.

Basic operations: int sum = 5 + 3;, string concatenation String fullName = 'John' + ' Doe';.

Real-life example: In a banking app, calculate interest:

dart
double principal = 1000.0;
double rate = 0.05;
double interest = principal * rate;
print('Interest: $interest'); // Output: Interest: 50.0

Advanced: Use BigInt for large numbers: BigInt largeNum = BigInt.from(12345678901234567890);.

Best practice: Use const for compile-time constants: const double gravity = 9.8;.

Exception: Division by zero throws IntegerDivisionByZeroException. Handle with try-catch:

dart
try {
int result = 10 ~/ 0;
} catch (e) {
print('Error: $e');
}

Pros: Efficient memory use. Cons: No unsigned types. Alternatives: C++ for low-level control.

2.4 Advanced Data Types: Lists, Maps, Sets, and Runes

  • List: Ordered collection, e.g., List<int> numbers = [1, 2, 3];. Add with numbers.add(4);.
  • Map: Key-value pairs, e.g., Map<String, int> scores = {'Alice': 90, 'Bob': 85};. Access: scores['Alice'].
  • Set: Unique items, e.g., Set<String> fruits = {'apple', 'banana'};.
  • Runes: For Unicode, e.g., handling emojis: Runes emoji = Runes('\u{1F600}');.

Real-life: In a shopping app, use List for cart items:

dart
List<String> cart = ['Milk', 'Bread'];
cart.add('Eggs');
print(cart); // [Milk, Bread, Eggs]

Advanced: Generics for type safety: List<Map<String, dynamic>> users = [{'name': 'Alice'}];.

Best practice: Use spread operators for combining: List<int> combined = [...list1, ...list2];.

Exception: Index out of range: Use try { list[10]; } catch (e) { print('Out of bounds'); }.

Pros: Built-in collections are versatile. Cons: No built-in queues (use List). Alternatives: Python lists for similar ease.

2.5 Type Inference with 'var', 'dynamic', and 'final/const'

  • var: Infers type at compile-time, can't change type.
  • dynamic: Can change type, but risky.
  • final: Assigned once, runtime.
  • const: Compile-time constant.

Example:

dart
var name = 'Dart'; // Inferred String
dynamic flexible = 10; flexible = 'Now string';
final int age = 30; // Can't reassign
const double pi = 3.14;

Real-life: In config files, use const for app constants.

Best practice: Prefer var over explicit types for brevity, but use types for clarity in APIs.

Exception: Type mismatch with dynamic can cause runtime errors—avoid unless necessary.

Pros: Flexibility with safety. Cons: Dynamic can lead to bugs. Alternatives: TypeScript's 'any'.

2.6 Real-Life Examples: Managing User Profiles in a Social App

Imagine building a social media app like Instagram. Users have profiles with name, age, friends list, and bio.

Code example (basic to advanced):

Basic profile:

dart
String username = 'user123';
int followers = 500;
bool isVerified = true;
List<String> friends = ['friend1', 'friend2'];
Map<String, dynamic> profile = {
'username': username,
'followers': followers,
'isVerified': isVerified,
'friends': friends
};
print(profile);

Advanced: Add validation:

dart
void createProfile(String name, int age) {
if (age < 13) {
throw Exception('Age must be at least 13');
}
var profile = {'name': name, 'age': age};
print('Profile created: $profile');
}
try {
createProfile('Kid', 12);
} catch (e) {
print('Error: $e');
}

In real scenarios, this handles user data storage, ensuring compliance like age restrictions for social apps. Extend with JSON serialization for API integration.

Pros: Data types make profiles efficient. Cons: Manual validation needed. Best practice: Use classes for complex profiles (covered later).

2.7 Best Practices, Exception Handling, Pros/Cons, and Alternatives

Best practices:

  • Use meaningful variable names.
  • Prefer immutable data with final/const for performance.
  • Enable strict mode for types.

Exception handling: Always wrap risky code in try-catch-finally. Custom exceptions: class InvalidAgeException implements Exception {}.

Pros of Dart data types: Null safety, performance. Cons: Steeper learning for dynamic lang users. Alternatives: Java for similar typing, Python for simplicity.

This section alone provides a strong base—now onto control structures.

3. Control Structures: Conditionals and Loops

Control structures direct code flow, essential for decision-making and repetition in apps.

3.1 Conditional Statements: if, if-else, else-if Ladders, and Ternary Operators

Basic if:

dart
int age = 18;
if (age >= 18) {
print('Adult');
}

If-else:

dart
if (age >= 18) {
print('Adult');
} else {
print('Minor');
}

Else-if ladder for grades:

dart
int score = 85;
if (score >= 90) {
print('A');
} else if (score >= 80) {
print('B');
} else {
print('C');
}

Ternary: String status = age >= 18 ? 'Adult' : 'Minor';.

Real-life: In a login system, check credentials.

Advanced: Combine with logical operators: if (age >= 18 && isCitizen) { print('Eligible to vote'); }.

Best practice: Avoid deep nesting; use early returns.

3.2 Switch-Case Statements for Multi-Way Branching

For discrete values:

dart
String day = 'Monday';
switch (day) {
case 'Monday':
print('Start of week');
break;
case 'Friday':
print('Weekend ahead');
break;
default:
print('Midweek');
}

Real-life: Menu selection in a game app.

Advanced: Switch on enums: enum Color { red, blue }; switch(color) {...}.

Pros: Cleaner than long if-else. Cons: Limited to equality checks.

3.3 Loops: for, while, do-while, and for-in Iterations

For loop:

dart
for (int i = 0; i < 5; i++) {
print(i);
}

While:

dart
int count = 0;
while (count < 5) {
print(count);
count++;
}

Do-while (runs at least once):

dart
int num = 5;
do {
print(num);
num--;
} while (num > 0);

For-in for collections:

dart
List<String> fruits = ['apple', 'banana'];
for (var fruit in fruits) {
print(fruit);
}

Real-life: Processing transaction logs in a finance app.

Advanced: Infinite loops with break: while (true) { if (condition) break; }.

Best practice: Use for-in for readability with iterables.

3.4 Break, Continue, and Nested Loops

Break exits loop, continue skips iteration.

Nested example:

dart
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (j == 1) continue;
print('$i-$j');
}
}

Real-life: Searching 2D grids in puzzle games.

Exception: Avoid unlabeled breaks in nested loops; use labels: outer: for (...) { break outer; }.

3.5 Real-Life Examples: Inventory Management System in an E-Commerce App

In an online store like Amazon, manage stock with conditionals and loops.

Basic: Check stock:

dart
int stock = 10;
if (stock > 0) {
print('Available');
} else {
print('Out of stock');
}

Advanced: Loop through items and update:

dart
List<Map<String, dynamic>> inventory = [
{'item': 'Shirt', 'stock': 5},
{'item': 'Pants', 'stock': 0}
];
for (var item in inventory) {
String status = item['stock'] > 0 ? 'In stock' : 'Sold out';
print('${item['item']}: $status');
if (item['stock'] == 0) {
// Notify supplier
print('Restock ${item['item']}');
}
}

Handle exceptions like invalid stock:

dart
try {
if (stock < 0) throw Exception('Negative stock invalid');
} catch (e) {
print('Error: $e');
}

This simulates real e-commerce logic, ensuring app responsiveness. Extend with databases for persistence.

Pros: Efficient for batch processing. Cons: Loops can be slow for large data—use streams for big datasets.

3.6 Best Practices, Exception Handling, Pros/Cons, and Alternatives

Best practices:

  • Use switch for enums.
  • Avoid mutable state in loops.
  • Profile loops for performance.

Exception handling: Catch loop errors like index errors.

Pros: Flexible control. Cons: Potential infinite loops. Alternatives: Recursion for tree traversals, but watch stack overflow.

4. Functions, Parameters, and Return Types

Functions encapsulate reusable code, key for modular apps.

4.1 Defining and Calling Functions: Basics and Syntax

Basic:

dart
void greet() {
print('Hello!');
}
greet();

With return:

dart
int add(int a, int b) {
return a + b;
}
print(add(2, 3)); // 5

Real-life: Utility functions in utilities class.

4.2 Parameters: Positional, Named, Optional, and Default Values

Positional: add(int a, int b)

Named: void info({String? name, int? age}) { ... } Call: info(name: 'Alice', age: 25);

Optional: void opt([String name = 'Guest']) { ... }

Real-life: API calls with optional params.

Advanced: Required named: {required String name}.

4.3 Return Types: Void, Single Values, and Multiple Returns via Tuples

Void for no return. Multiple: Use records (Dart 3+): (int, String) getInfo() => (42, 'Answer');

Example: var (num, text) = getInfo();

4.4 Arrow Functions and Anonymous Functions

Arrow: int square(int x) => x * x;

Anonymous: var anon = (int x) => x * 2;

Real-life: Callbacks in event handlers.

4.5 Higher-Order Functions and Closures

Higher-order: Functions taking/returning functions.

Example: void execute(Function op) { op(); }

Closure: Captures variables.

dart
Function counter() {
int count = 0;
return () => count++;
}
var c = counter();
print(c()); // 0
print(c()); // 1

Advanced: In state management.

4.6 Real-Life Examples: Processing Orders in a Food Delivery App

In apps like Uber Eats, process orders.

Basic function:

dart
double calculateTotal(List<double> prices) {
double total = 0;
for (var price in prices) {
total += price;
}
return total;
}
print(calculateTotal([10.5, 5.0])); // 15.5

Advanced with params and exceptions:

dart
double calcOrder({required List<double> items, double discount = 0.0}) {
if (items.isEmpty) throw Exception('No items');
double sum = items.reduce((a, b) => a + b);
return sum - (sum * discount);
}
try {
print(calcOrder(items: [10, 20], discount: 0.1)); // 27.0
} catch (e) {
print('Error: $e');
}

This handles real orders, adding taxes or fees. Pros: Reusable. Cons: Overuse leads to complexity.

4.7 Best Practices, Exception Handling, Pros/Cons, and Alternatives

Best practices:

  • Keep functions short (<50 lines).
  • Use named params for clarity.

Exception: Throw specific exceptions.

Pros: Modularity. Cons: Overhead in deep calls. Alternatives: Lambdas in Kotlin.

5. Object-Oriented Programming in Dart: Classes, Objects, and Inheritance

OOP models real-world entities.

5.1 Classes and Objects: Constructors, Properties, and Methods

Class:

dart
class Person {
String name;
int age;
Person(this.name, this.age); // Constructor
void introduce() {
print('Hi, I\'m $name, $age years old.');
}
}
var p = Person('Alice', 30);
p.introduce();

Properties: Getters/setters.

dart
class Rectangle {
double _width;
double get width => _width;
set width(double value) {
if (value < 0) throw Exception('Negative width');
_width = value;
}
}

Real-life: User models in apps.

5.2 Inheritance: Single, Multi-Level, and Hierarchical

Single:

dart
class Animal {
void eat() { print('Eating'); }
}
class Dog extends Animal {
void bark() { print('Woof'); }
}
var d = Dog();
d.eat();
d.bark();

Multi-level: Class Puppy extends Dog.

Hierarchical: Multiple subclasses from Animal.

5.3 Overriding Methods and Using 'super'

dart
class Cat extends Animal {
@override
void eat() {
super.eat();
print('Meow while eating');
}
}

5.4 Abstract Classes, Interfaces, and Mixins

Abstract:

dart
abstract class Shape {
double area();
}

Interface: Classes act as interfaces.

Mixin: mixin Flyable { void fly() { ... } } class Bird with Flyable {}

Advanced: Multiple mixins.

5.5 Encapsulation, Polymorphism, and Abstraction in Practice

Encapsulation: Private members with _.

Polymorphism: Treat subclasses as super.

Abstraction: Hide details.

5.6 Real-Life Examples: Building a Vehicle Rental System

For a rental app like Zipcar.

Basic class:

dart
class Vehicle {
String model;
double pricePerDay;
Vehicle(this.model, this.pricePerDay);
double calculateRental(int days) {
return pricePerDay * days;
}
}

Inheritance:

dart
class Car extends Vehicle {
int seats;
Car(String model, double price, this.seats) : super(model, price);
@override
double calculateRental(int days) {
double base = super.calculateRental(days);
return base + (seats > 4 ? 10 : 0); // Extra for larger cars
}
}
var sedan = Car('Toyota', 50.0, 5);
print(sedan.calculateRental(3)); // 180.0

Advanced with exceptions:

dart
class Bike extends Vehicle {
@override
double calculateRental(int days) {
if (days <= 0) throw Exception('Invalid days');
return super.calculateRental(days) * 0.8; // Discount
}
}
try {
var bike = Bike('Honda', 20.0);
print(bike.calculateRental(0));
} catch (e) {
print('Error: $e');
}

Mixin for electric:

dart
mixin Electric {
void charge() { print('Charging'); }
}
class ElectricCar extends Car with Electric {
ElectricCar(String model, double price, int seats) : super(model, price, seats);
}
var eCar = ElectricCar('Tesla', 100.0, 4);
eCar.charge();

This models real rental logic, calculating costs with features. Pros: Scalable. Cons: Inheritance abuse leads to fragility.

5.7 Best Practices, Exception Handling, Pros/Cons, and Alternatives

Best practices:

  • Favor composition over inheritance.
  • Use abstract for templates.

Exception: Validate in constructors.

Pros: Reusability. Cons: Tight coupling. Alternatives: Functional programming in Haskell.

6. Asynchronous Programming: Futures, Async, and Await

Async keeps apps responsive during I/O.

6.1 Understanding Synchronous vs. Asynchronous Code

Sync blocks: print('Wait'); sleep(2); print('Done');

Async doesn't block.

6.2 Futures: Creating, Chaining, and Handling Errors

Future:

dart
Future<String> fetchData() {
return Future.delayed(Duration(seconds: 2), () => 'Data fetched');
}
fetchData().then((data) => print(data));

Chaining: .then((v) => anotherFuture(v))

Error: .catchError((e) => print(e));

6.3 Async and Await Keywords for Readable Async Code

dart
Future<void> main() async {
try {
String data = await fetchData();
print(data);
} catch (e) {
print('Error: $e');
}
}

Real-life: API calls.

6.4 Streams for Continuous Data Flows

Stream:

dart
Stream<int> countStream() async* {
for (int i = 1; i <= 3; i++) {
yield i;
}
}
countStream().listen((num) => print(num));

For real-time updates.

6.5 Isolates for Concurrency in Dart

Isolates: Separate memory threads.

dart
import 'dart:isolate';
void isolateFunc(SendPort port) {
port.send('From isolate');
}
void main() async {
ReceivePort receive = ReceivePort();
Isolate.spawn(isolateFunc, receive.sendPort);
print(await receive.first);
}

Advanced for heavy computations.

6.6 Real-Life Examples: Fetching Weather Data in a Mobile App

In a weather app like AccuWeather.

Basic future:

dart
Future<Map<String, dynamic>> getWeather() async {
// Simulate API
await Future.delayed(Duration(seconds: 1));
return {'temp': 25, 'condition': 'Sunny'};
}

Usage:

dart
Future<void> displayWeather() async {
try {
var weather = await getWeather();
print('Temperature: ${weather['temp']}°C, ${weather['condition']}');
} catch (e) {
print('Failed to fetch: $e');
}
}
displayWeather();

Advanced with stream for live updates:

dart
Stream<Map<String, dynamic>> weatherStream() async* {
while (true) {
yield await getWeather();
await Future.delayed(Duration(minutes: 5));
}
}
weatherStream().listen((data) => print(data));

Handle exceptions like network errors: Throw Exception('No internet').

This ensures the app doesn't freeze during fetches. Pros: Responsive UIs. Cons: Complexity in error propagation. Best practice: Use try-await-catch.

6.7 Best Practices, Exception Handling, Pros/Cons, and Alternatives

Best practices:

  • Await in async functions.
  • Use Completer for custom futures.

Exception: Propagate with rethrow.

Pros: Modern async model. Cons: Callback hell without await. Alternatives: Promises in JS.

7. Practical Exercise: Building a Simple Dart Calculator Program

Apply all concepts in a calculator.

7.1 Step-by-Step Project Setup

  1. Create file calculator.dart.
  2. Import dart:io for input.

7.2 Implementing Basic Operations: Addition, Subtraction, Multiplication, Division

Class:

dart
class Calculator {
double add(double a, double b) => a + b;
double subtract(double a, double b) => a - b;
double multiply(double a, double b) => a * b;
double divide(double a, double b) {
if (b == 0) throw Exception('Division by zero');
return a / b;
}
}

7.3 Adding Advanced Features: Error Handling, User Input Validation, and History Logging

Main with input:

dart
import 'dart:io';
void main() {
var calc = Calculator();
List<String> history = [];
while (true) {
print('Enter operation (add/sub/mul/div/exit):');
String op = stdin.readLineSync()!.trim().toLowerCase();
if (op == 'exit') break;
print('Enter first number:');
double a = double.parse(stdin.readLineSync()!);
print('Enter second number:');
double b = double.parse(stdin.readLineSync()!);
try {
double result;
switch (op) {
case 'add':
result = calc.add(a, b);
break;
case 'sub':
result = calc.subtract(a, b);
break;
case 'mul':
result = calc.multiply(a, b);
break;
case 'div':
result = calc.divide(a, b);
break;
default:
throw Exception('Invalid operation');
}
history.add('$op $a $b = $result');
print('Result: $result');
} catch (e) {
print('Error: $e');
}
print('History:');
for (var entry in history) {
print(entry);
}
}
}

Validation: Use try-parse for inputs.

7.4 Real-Life Integration: Extending to a Budget Tracker App

Extend calculator for budget: Add functions for expense tracking, using maps for categories.

Example: Map<String, double> expenses = {}; Add via functions.

This turns it into a practical tool for personal finance apps.

7.5 Testing and Debugging Your Calculator

Test cases: Input 10 + 5 = 15, divide by 0 error.

Debug: Use print or IDE breakpoints.

Pros: Hands-on learning. Cons: Console-only; integrate with Flutter for UI.

No comments:

Post a Comment

Thanks for your valuable comment...........
Md. Mominul Islam

Post Bottom Ad

Responsive Ads Here