On this page25 sections
- Prerequisites
- Connection With Previous Lectures
- Learning Objectives
- 1. Two Ways to Hold "Any Value"
- 2. Every Value Is an Object
- 3. Declaring an Object Variable
- 4. What You Can Do with an Object
- 5. What You Cannot Do with an Object
- 6. Using the Real Value with as
- 7. Declaring a dynamic Variable
- 8. dynamic Switches the Checks Off
- 9. Compile Time vs Run Time
- 10. Copying into a Specific Type
- 11. var, Object, and dynamic Side by Side
- 12. Which One Should You Use?
- 13. A Real-World Example
- Code Examples
- Common Beginner Mistakes
- Best Practices
- Mini Challenge
- Practice Questions
- Practice Answers
- Quick Revision
- Key Takeaways
- What's Next?
Lecture 11 — dynamic vs Object
| Category | 2 — Variables & Data Types |
| Lecture | 011 of 140 |
| Estimated video length | 8 min |
| Target | Dart 3.12.2 |
| Level | Beginner |
Every variable so far held one kind of value.
Objectanddynamicboth let a variable hold any value — but one keeps Dart checking your code, and the other switches the checks off.
Contents
Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways
Every error message in this lecture is real. Each one was produced by running the code shown on Dart 3.12.2, so you will recognize it when you meet it yourself.
Prerequisites
Students should already understand, from Lectures 004–010:
- declaring variables with an explicit type and with
var - why
var score;without a value lets any value in (Lecture 005) - the types
String,int,double, andbool, and string properties such aslength - checking a type with
is, reading it withruntimeType, and casting withas(Lecture 010)
Connection With Previous Lectures
Every variable we have written has one fixed type:
var age = 20; // an int, foreverBut some values can be of different kinds: a setting might be true, 25, or 'dark'.
No type we know holds all three. In Lecture 005, var score; accepted anything — and quietly
turned type checking off. This lecture shows the two proper ways to hold "any value", and
why they behave very differently.
Learning Objectives
By the end of this lecture you will be able to:
- Explain why every value in Dart is an
Object - Declare variables of type
Objectanddynamic - Recognize what Dart allows you to do with an
Objectvalue - Use
asto work with the real value inside anObjectvariable - Explain how
dynamicswitches off compile-time type checking - Tell a compile-time error from a run-time crash
- Compare
var,Object, anddynamic - Choose the safest type for a variable
1. Two Ways to Hold "Any Value"
Dart gives you two types that accept a value of any kind: Object and dynamic.
Analogy — imagine two boxes that hold anything. The
Objectbox is sealed and labeled "something": you can carry it and show it, but before using what is inside you must say what it is. Thedynamicbox is open: Dart trusts you to use the contents correctly, and if you guessed wrong you find out only while the program runs.
Both hold the same values. What differs is how much Dart checks.
2. Every Value Is an Object
Object is the most general type in Dart. Every value you have met — text, whole numbers,
decimals, true and false — is an Object:
void main() {
print('Ali' is Object);
print(20 is Object);
print(99.5 is Object);
print(true is Object);
}true
true
true
trueYour editor may underline these lines with "Unnecessary type check; the result is always
'true'" — Dart already knows the answer. A String is a String and an Object, just
as Ali is a student and also a person.
3. Declaring an Object Variable
Because every value is an Object, a variable of type Object can hold any of them, and can
be changed to a value of a different kind:
void main() {
Object item = 'Ali';
print(item);
item = 20;
print(item);
item = true;
print(item);
}Ali
20
trueruntimeType (Lecture 010) shows what kind of value is inside right now:
void main() {
Object item = 'Ali';
print(item.runtimeType);
item = 20;
print(item.runtimeType);
}String
int4. What You Can Do with an Object
Dart only lets you do with an Object variable what works for every value: print it,
put it in a string, convert it with toString(), compare it with ==, and read its
runtimeType.
void main() {
Object price = 250;
print(price);
print('Price: $price');
print(price.toString());
print(price == 250);
}250
Price: 250
250
true5. What You Cannot Do with an Object
length belongs to strings, not to every value. Dart sees only the type Object, so it
refuses — even though the value inside really is a String:
void main() {
Object item = 'Ali';
print(item.length);
}Error: The getter 'length' isn't defined for the type 'Object'.
- 'Object' is from 'dart:core'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'length'.
print(item.length);
^^^^^^Arithmetic is refused for the same reason — not every value can be added:
void main() {
Object price = 100;
print(price + 50);
}Error: The operator '+' isn't defined for the type 'Object'.
- 'Object' is from 'dart:core'.
Try correcting the operator to an existing operator, or defining a '+' operator.
print(price + 50);
^These are compile-time errors: Dart stops before the program runs a single line.
6. Using the Real Value with as
To use the value as what it really is, tell Dart with as (Lecture 010). The parentheses
make the cast happen first:
void main() {
Object item = 'Ali';
print((item as String).length);
Object price = 100;
print((price as int) + 50);
}3
150as is a promise. If the promise is wrong, the program crashes while running:
void main() {
Object item = 20;
print((item as String).length);
}Unhandled exception:
type 'int' is not a subtype of type 'String' in type castDart also prints a few lines showing where the crash happened. We will learn to read them
when we cover errors and exceptions, starting in Lecture 083. Check with is before you
cast when you are not sure; in Lecture 022, if will let you act on that check.
7. Declaring a dynamic Variable
A dynamic variable also holds any value and can change kind:
void main() {
dynamic value = 'Sara';
print(value);
value = 18;
print(value);
}Sara
18The difference shows when you use the value. With dynamic, Dart lets you write anything —
no cast needed:
void main() {
dynamic name = 'Sara';
print(name.length);
print(name.toUpperCase());
}4
SARA8. dynamic Switches the Checks Off
Dart did not check name.length — it simply trusted you. When the trust is misplaced, the
mistake is not caught before the program runs. It crashes instead:
void main() {
dynamic value = 20;
print(value.length);
}Unhandled exception:
NoSuchMethodError: Class 'int' has no instance getter 'length'.
Receiver: 20
Tried calling: lengthEven a simple typo slips through:
void main() {
dynamic name = 'Sara';
print(name.toUpperCse());
}Unhandled exception:
NoSuchMethodError: Class 'String' has no instance method 'toUpperCse'.
Receiver: "Sara"
Tried calling: toUpperCse()With Object or String, Dart would have pointed at this typo before running anything.
9. Compile Time vs Run Time
This is the heart of the lecture.
- A compile-time error appears before the program starts. Nothing runs. Safe.
- A run-time error appears while the program runs — perhaps halfway through its work, perhaps only on a user's computer. Dangerous.
| Mistake | With Object | With dynamic |
|---|---|---|
Using length on a value | compile-time error | allowed — crashes if the value has none |
| A typo in a method name | compile-time error | crashes when that line runs |
Adding with + | compile-time error | allowed — crashes if the value can't be added |
Object makes you prove your intent with as. dynamic takes your word for it.
10. Copying into a Specific Type
The same difference appears when you copy the value into a typed variable. From Object,
Dart demands a cast:
void main() {
Object item = 'Ali';
String name = item;
print(name);
}Error: A value of type 'Object' can't be assigned to a variable of type 'String'.
- 'Object' is from 'dart:core'.
String name = item;
^Write String name = item as String; and it runs. From dynamic, Dart allows the copy
without asking — and crashes if the value is the wrong kind:
void main() {
dynamic value = 20;
String name = value;
print(name);
}Unhandled exception:
type 'int' is not a subtype of type 'String'11. var, Object, and dynamic Side by Side
void main() {
var a = 10; // int — fixed type
Object b = 10; // any value, checked
dynamic c = 10; // any value, unchecked
b = 'ten';
c = 'ten';
print(a);
print(b);
print(c);
}10
ten
ten| Holds any value? | Dart checks how you use it? | |
|---|---|---|
var a = 10; | No — int only | Yes |
Object b = 10; | Yes | Yes |
dynamic c = 10; | Yes | No |
Writing a = 'ten'; would be an error, as in Lecture 005. And remember var score; with no
value: that variable is dynamic, which is why it accepted anything.
12. Which One Should You Use?
Pick the most specific type that fits:
- A specific type (
String,int, …) orvar— almost always. Object— when a value truly can be of any kind. Dart keeps checking for you.dynamic— only when you must, such as data from outside the program. You will meet this with JSON in Lectures 108–109.
There is one more difference, to do with missing values — we will meet it in Lectures 012–013.
13. A Real-World Example
A sign-up form gives us two answers. The name arrives as text; the age arrives as text too,
because people type it. We hold both as Object, and use as to say what each one is:
void main() {
Object nameAnswer = 'Zayan';
Object ageAnswer = '6';
var name = nameAnswer as String;
var age = int.parse(ageAnswer as String);
print('Name: ${name.toUpperCase()}');
print('Letters: ${name.length}');
print('Age next year: ${age + 1}');
print('Answer types: ${nameAnswer.runtimeType}, ${ageAnswer.runtimeType}');
}Name: ZAYAN
Letters: 5
Age next year: 7
Answer types: String, StringAfter as String, name is a real String with toUpperCase() and length, and
int.parse (Lecture 010) turns the age text into an int. Dart checked every step before
the program ran.
Code Examples
Example 1 — Every Value Is an Object
void main() {
print('Sara' is Object);
print(42 is Object);
print(3.5 is Object);
print(false is Object);
}true
true
true
trueExample 2 — An Object Variable Changing Kind
void main() {
Object item = 'Ali';
print('$item is a ${item.runtimeType}');
item = 7.5;
print('$item is a ${item.runtimeType}');
}Ali is a String
7.5 is a doubleExample 3 — Casting an Object with as
void main() {
Object word = 'Dart';
var text = word as String;
print(text.length);
print(text.toUpperCase());
}4
DARTExample 4 — A dynamic Variable Changing Kind
void main() {
dynamic value = 10;
print(value.runtimeType);
value = 'ten';
print(value.runtimeType);
}int
StringExample 5 — Using dynamic Without a Cast
void main() {
dynamic city = 'Lahore';
print(city.length);
print(city.toLowerCase());
}6
lahoreExample 6 — Checking Before You Cast
void main() {
Object answer = 25;
print(answer is int);
print(answer is String);
print((answer as int) * 2);
}true
false
50How it works
answer is intprintstrue, so casting tointis safe.answer is Stringprintsfalse— casting toStringwould crash.- After
as int, multiplication is allowed:25 * 2is50.
Example 7 — Student Marks
void main() {
Object student = 'Ali';
Object math = 80;
Object science = 75;
var total = (math as int) + (science as int);
print('Student: $student');
print('Total: $total');
}Student: Ali
Total: 155How it works
studentis only printed, which works for everyObject— no cast needed.- The marks must be added, so each is cast to
intfirst.
Example 8 — Shopping Total
void main() {
Object product = 'Notebook';
Object price = 500;
Object quantity = '3';
var total = (price as int) * int.parse(quantity as String);
print('Product: $product');
print('Total: $total');
}Product: Notebook
Total: 1500How it works
priceholds anint, soas intis enough.quantityholds the text'3', so it is cast toStringand converted withint.parse.- Casting
quantitystraight tointwould crash: the value is aString, not anint.
Example 9 — Bank Balance
void main() {
Object owner = 'Sara';
Object balance = 1000.0;
Object deposit = 250.5;
var newBalance = (balance as double) + (deposit as double);
print('Owner: $owner');
print('Balance: $newBalance');
}Owner: Sara
Balance: 1250.5How it works
- Both amounts hold a
double, so each is cast todoublebefore adding. newBalanceis inferred asdouble:1250.5.
Example 10 — Temperature with dynamic
void main() {
dynamic celsius = 25.0;
var fahrenheit = celsius * 9 / 5 + 32;
print('Celsius: $celsius');
print('Fahrenheit: $fahrenheit');
print(fahrenheit.runtimeType);
}Celsius: 25.0
Fahrenheit: 77.0
doubleHow it works
celsiusisdynamic, so Dart allows the arithmetic without a cast.- A calculation on a
dynamicvalue gives adynamicresult, sofahrenheitis inferred asdynamictoo — the unchecked type spreads. runtimeTypestill reports the real value, adouble.
Common Beginner Mistakes
1. Using a String property on an Object variable
void main() {
Object item = 'Ali';
// print(item.length); // ✗
}Error: The getter 'length' isn't defined for the type 'Object'.Cast first: (item as String).length.
2. Doing arithmetic on an Object variable
void main() {
Object price = 100;
// print(price + 50); // ✗
}Error: The operator '+' isn't defined for the type 'Object'.Write (price as int) + 50.
3. Copying an Object into a typed variable without a cast
void main() {
Object item = 'Ali';
// String name = item; // ✗
}Error: A value of type 'Object' can't be assigned to a variable of type 'String'.Write String name = item as String;.
4. Casting to the wrong type
void main() {
Object item = 20;
// print((item as String).length); // ✗ crashes while running
}Unhandled exception:
type 'int' is not a subtype of type 'String' in type castas does not convert — it only promises. Check with is first, or convert with the tools
from Lecture 010 (toString(), int.parse).
5. Using dynamic to make an error go away
void main() {
dynamic value = 20;
// print(value.length); // ✗ compiles, then crashes
}Unhandled exception:
NoSuchMethodError: Class 'int' has no instance getter 'length'.dynamic does not fix the mistake — it hides it until the program runs.
Best Practices
- Use a specific type or
varwhenever you know what kind of value a variable holds. - When a value really can be of any kind, prefer
Objecttodynamic. - Keep
dynamicfor data from outside the program, and convert it to a specific type as soon as possible. - Cast once into a new, typed variable (
var name = item as String;) instead of casting again on every line. - Check with
isbefore casting when you are not sure what a value is. - Always initialize
varvariables, so they never becomedynamicby accident.
Mini Challenge
A quiz app stores Sara's answers as Object: her name 'Sara', her score 45, and the
bonus points as the text '5'. Print her name in capitals and her final score.
Your program should print exactly:
Player: SARA
Final score: 50Try it yourself before opening the solution.
Show solution
void main() {
Object player = 'Sara';
Object score = 45;
Object bonus = '5';
var name = player as String;
var finalScore = (score as int) + int.parse(bonus as String);
print('Player: ${name.toUpperCase()}');
print('Final score: $finalScore');
}Player: SARA
Final score: 50How it works
playeris cast toStringsotoUpperCase()is available.scoreholds anint;bonusholds text, so it is cast toStringand parsed.45 + 5gives50.
Practice Questions
Work through these in order — they run from beginner to application to challenge. Every question gives you exact values, so you can compare your output with the answers.
Beginner
- Declare
Object item = 'Karachi';, print it, then change it to2026and print it again. - Print whether
12,'Ali', andfalseare each anObject, one result per line. - Declare
dynamic value = 3.5;and print itsruntimeType. Then assign'three'to it and print itsruntimeTypeagain.
Application
-
Declare
Object word = 'Flutter';. Useasto print the number of letters in it. -
Declare
Object price = 450;. Useasto print the price after adding50. -
This program does not compile. Fix it without changing the type
Object, so that it printsZAYAN:void main() { Object name = 'Zayan'; print(name.toUpperCase()); } -
Predict the output without running it, then check. Which line would be a compile-time error if
xwere declared asObjectinstead?void main() { dynamic x = 'Ali'; print(x.length); x = 7; print(x * 3); } -
Ali's marks are stored as
Object math = 70;andObject english = 88;. PrintTotal: 158.
Challenge
-
A form stores
Object balanceText = '1500';andObject deposit = 500;. PrintBalance: 2000. -
This program compiles but crashes. Explain in one sentence why, then fix it by changing one line so it prints
Letters: 2:void main() { dynamic age = 25; print('Letters: ${age.length}'); }
Practice Answers
Question 1 — Solution
void main() {
Object item = 'Karachi';
print(item);
item = 2026;
print(item);
}Karachi
2026Question 2 — Solution
void main() {
print(12 is Object);
print('Ali' is Object);
print(false is Object);
}true
true
trueQuestion 3 — Solution
void main() {
dynamic value = 3.5;
print(value.runtimeType);
value = 'three';
print(value.runtimeType);
}double
StringQuestion 4 — Solution
void main() {
Object word = 'Flutter';
print((word as String).length);
}7Question 5 — Solution
void main() {
Object price = 450;
print((price as int) + 50);
}500Question 6 — Solution
Cast the value to String before calling toUpperCase():
void main() {
Object name = 'Zayan';
print((name as String).toUpperCase());
}ZAYANQuestion 7 — Solution
void main() {
dynamic x = 'Ali';
print(x.length);
x = 7;
print(x * 3);
}3
21With Object, both x.length and x * 3 would be compile-time errors.
Question 8 — Solution
void main() {
Object math = 70;
Object english = 88;
var total = (math as int) + (english as int);
print('Total: $total');
}Total: 158Question 9 — Solution
void main() {
Object balanceText = '1500';
Object deposit = 500;
var balance = int.parse(balanceText as String) + (deposit as int);
print('Balance: $balance');
}Balance: 2000balanceText holds text, so it is cast to String and parsed; deposit already holds an
int.
Question 10 — Solution
It crashes because age holds an int, which has no length — and dynamic hid that
mistake until the program ran. Convert the number to text first:
void main() {
dynamic age = 25;
print('Letters: ${age.toString().length}');
}Letters: 2Quick Revision
- Why can an
Objectvariable hold any value? - Which five things can you do with any
Object? - What does
asdo, and what happens if the cast is wrong? - What does
dynamicswitch off? - What is the difference between a compile-time error and a run-time error?
- Which is safer for "any value":
Objectordynamic? Why? - What type does
var score;(no value) give a variable?
Key Takeaways
- Every value in Dart is an
Object. - Both
Objectanddynamicvariables can hold any value and change kind. Objectkeeps type checking on: you may only do what works for every value until you cast withas.dynamicswitches type checking off: anything compiles, and mistakes become run-time crashes.- Compile-time errors are safe; run-time errors reach the running program.
aspromises a type — it does not convert one.varwithout a value creates adynamicvariable.- Prefer a specific type, then
Object, and usedynamiconly when you must.
What's Next?
Lecture 012 — Introduction to Null Safety. So far every variable has held a real value.
But real programs often deal with values that are missing — a middle name nobody entered,
a score not recorded yet. Dart has a special value for "nothing", null, and a system that
stops it from crashing your programs. That is where Category 3 begins.