Prequel
you have read the theory. variables, null safety, collections, OOP, async. you know what the words mean.
but reading code and writing code are different things. the neurons that let you produce dart are not built by reading explanations. they are built by getting stuck, figuring it out, and running it. that is what these exercises do.
10 exercises. each one targets something from the last two posts. they start simple and get harder, in that order. every concept you solve here compounds directly into real flutter work.
no answers in this post. look things up, make mistakes, make it run.
Exercise 1 - Variables
covers var, explicit type annotations, final, const, .runtimeType, nullable types
directions
- declare at least one variable using each of:
var, an explicit type,final,const. use at least four types:int,double,String,bool - try to reassign a
finalvariable and aconstvariable. note what happens and put the error in a comment - declare a nullable
String?and a non-nullableString. assignnullto the nullable one. try assigningnullto the non-nullable one and note what the compiler says - print the runtime type of each variable using
.runtimeType
expected output
42 is int
3.14 is double
Dart is String
true is bool
name is final, cannot be reassigned
PI is const, cannot be reassigned
Nullable string: null
Non-nullable string: Hello
Exercise 2 - Control Flow
covers if/else, switch, for, while, break, continue
directions
- create a list of integers from 1 to 20
- use a
forloop withcontinueto print only even numbers, skipping odd ones - write a
switchstatement that classifies a number as"small"(1 to 5),"medium"(6 to 10), or"large"(11 to 20). run it on three different values - use a
whileloop to find the first number greater than 15 that is divisible by both 3 and 4.breakwhen you find it
expected output
Even numbers: 2 4 6 8 10 12 14 16 18 20
3 → small
8 → medium
17 → large
First match (>15, div by 3&4): 24
Exercise 3 - Functions
covers named parameters, optional positional parameters, default values, arrow functions, higher-order functions
directions
- write a function
greetthat takes a requirednameand a named optionaltitle(default:"Dev"). it should return a greeting string - write an arrow function
squarethat returns the square of a number - write a function
describewith a required param and an optional positional param[String suffix = '!'] - write a higher-order function
applyTwicethat takes a function and a value, applies the function twice, and returns the result - call
applyTwicewithsquareand the value3
expected output
Hello, Dev Rakhul!
Hello, Engineer Arjun!
Square of 5: 25
described: Cool Dart!
applyTwice(square, 3): 81
Exercise 4 - Strings
covers string interpolation, multi-line strings, .toUpperCase(), .contains(), .split(), .trim(), .replaceAll(), .startsWith(), raw strings
directions
- build a full name from
firstNameandlastNameusing string interpolation - write a multi-line string using
"""with three lines, any quote or text about code you want - demonstrate each of these in a print:
.toUpperCase(),.contains(),.split(),.trim(),.replaceAll(),.startsWith() - print a raw string
r'\n is not a newline here'and then a regular string that actually uses\n - reverse a string without using any built-in reverse method
expected output
Full name: Ada Lovelace
--- Quote ---
Code is poetry
written in logic
read by machines
---
Upper: ADA LOVELACE
Contains 'Love': true
Split by ' ': [Ada, Lovelace]
Trimmed: "Dart"
Replaced: Hello World
Raw: \n is not a newline here
With escape:
new line here
Reversed: ecalevoL adA
Exercise 5 - Collections
covers List, Map, Set, the spread operator ..., collection-if, collection-for
directions
- create a
List<String>of 5 programming languages. add one, remove one, sort it, then iterate with index - create a
Map<String, int>of language to year created. add a new entry, check if a key exists, loop through all entries and print them - create two
Set<int>s and compute their union, intersection, and difference - use collection-if to conditionally include an element in a new list
- use collection-for to build a list of uppercased strings from an existing list
- use the spread operator
...to merge two lists into one
expected output
Languages (sorted): [C, Dart, Go, Python, Rust]
After add/remove: [C, Dart, Python, Rust]
Map entry — Dart: 2011
Has 'Go': false
Union: {1, 2, 3, 4, 5}
Intersection: {3}
Difference: {1, 2}
Conditional list: [dart, flutter, firebase]
Uppercased: [DART, FLUTTER, FIREBASE]
Merged: [C, Dart, Python, Go, Java]
Exercise 6 - Classes
covers instance variables, private fields, constructors, named constructors, getters, computed properties
directions
- create a
BankAccountclass withowner(String) and a private_balance(double) - add a default constructor and a named constructor
BankAccount.empty(owner)that initializes the balance to zero - add
deposit(amount)andwithdraw(amount)methods.withdrawshould print an error message if funds are insufficient and leave the balance unchanged - add a getter
balancethat exposes the private_balance - add a computed getter
isRichthat returnstrueif the balance is above 10000 - create both types of accounts, run through deposits and withdrawals, and print the state after each step
expected output
Account: Rakhul | Balance: ₹5000.0
After deposit: ₹8000.0
After withdraw: ₹5500.0
Insufficient funds!
Balance unchanged: ₹5500.0
Is rich: false
Empty account — Arjun | Balance: ₹0.0
Exercise 7 - Null Safety
covers ?, ??, ??=, !, null-aware access ?., null-aware cascade ?..
directions
- declare a nullable
String? city. print it before and after assigning a value - use
??to print the city or"Unknown City"as a fallback when it is null - use
??=to assign"Mumbai"only ifcityis null. then try??=again with a different value and confirm it did not change - create a nullable
List<String>?. use?.lengthto safely access its length before and after giving it a value - create a simple class with a method that returns a string. make a nullable instance of it and call the method safely using
?. - use the null assertion operator
!on a known non-null nullable variable. add a comment in your code explaining what would happen at runtime if you used!on an actual null value
expected output
city is: null
city with fallback: Unknown City
After ??= 'Mumbai': Mumbai
Assigning again with ??=... still: Mumbai
Nullable list length: null
After init, length: 3
Safe method call result: HELLO
Null assertion result: 42
Exercise 8 - Inheritance
covers abstract, extends, @override, implements, polymorphism
directions
- write an
abstractclassShapewith an abstract methodarea()and a concrete methoddescribe()that prints"I am a [runtimeType]" - create
CircleandRectanglethat extendShapeand implementarea() - create an interface (an abstract class)
Drawablewith a methoddraw() - make
RectangleimplementDrawableas well as extendShape - create a
List<Shape>with oneCircleand oneRectangle, loop through it, and call both.area()and.describe()on each shape
expected output
I am a Circle
Circle area: 78.54
I am a Rectangle
Rectangle area: 24.0
Rectangle is being drawn on canvas
Polymorphic loop:
Circle → area: 78.54
Rectangle → area: 24.0
Exercise 9 - Mixins
covers mixin, with, the on constraint, mixin composition
directions
- create a mixin
Loggerwith a methodlog(String message)that prints[LOG] message - create a mixin
Validatorwith a methodisValidEmail(String email)that returns abool - create a class
UserServicewith no parent class. give it both mixins usingwith - create a base class
Modelwith anidfield and anamefield - create a mixin
Serializablewith anon Modelconstraint. give it atoJson()method that reads from theModelfields and returns aMap - create a class that extends
Modeland usesSerializable. create an instance and calltoJson()on it
expected output
[LOG] UserService initialized
Email valid (test@dart.dev): true
Email valid (notanemail): false
[LOG] Validating user input...
User JSON: {id: 1, name: Rakhul}
Exercise 10 - Async
covers Future, async/await, .then(), .catchError(), Future.wait, try/catch
directions
- write
Future<String> fetchUser(int id)usingFuture.delayedto simulate a 2-second network call. it should return"User: $id"for valid ids, or throw an exception ifidis negative - call it with
async/awaitand print the result - call it again using
.then()and.catchError()instead - write two separate async functions
fetchPosts()andfetchComments(), each with a short simulated delay - run both in parallel using
Future.waitand print both results once they are done - call
fetchUserwith a negative id inside atry/catchblock and handle the error
expected output
Fetching user...
User: 42
Then-style: User: 7
Fetching posts and comments in parallel...
Done: [Posts loaded, Comments loaded]
Error caught: Invalid user ID
That's Part 1
ten exercises, ten concepts. variables, control flow, functions, strings, collections, classes, null safety, inheritance, mixins, async.
if you got through all of them, you can write dart. not just understand it when someone else wrote it. actually write it.
part 2 goes deeper. sealed classes, streams, isolates, and the patterns you will hit in real flutter apps.
