116

According to this article:

As you might know, dynamic (as it is now called) is the stand-in type when a static type annotation is not provided.

So, what is the difference between dynamic and var? When to use?

Gero
  • 12,993
  • 25
  • 65
  • 106
  • 4
    I believe, a variable marked as `var` can be initialized as any type, but after that can only be assigned expressions that return that type. While a variable marked as `dynamic` can both be initialized as any type, and then assigned to expressions which can change that type. Hence, the type being dynamic after initialization of the variable. – tim-montague Nov 19 '21 at 22:41

15 Answers15

136

dynamic is a type underlying all Dart objects. You shouldn't need to explicitly use it in most cases.

var is a keyword, meaning "I don't care to notate what the type is here." Dart will replace the var keyword with the initializer type, or leave it dynamic by default if there is no initializer.

Use var if you expect a variable assignment to change during its lifetime:

var msg = "Hello world.";
msg = "Hello world again.";

Use final if you expect a variable assignment to remain the same during its lifetime:

final msg = "Hello world.";

Using final (liberally) will help you catch situations where you accidentally change the assignment of a variable when you didn't mean to.

Note that there is a fine distinction between final and const when it comes to objects. final does not necessarily make the object itself immutable, whereas const does:

// can add/remove from this list, but cannot assign a new list to fruit.
final fruit = ["apple", "pear", "orange"];
fruit.add("grape");

// cannot mutate the list or assign a new list to cars.
final cars = const ["Honda", "Toyota", "Ford"];

// const requires a constant assignment, whereas final will accept both:
const names = const ["John", "Jane", "Jack"];
Tharindu Lakshan
  • 3,995
  • 6
  • 24
  • 44
John Evans
  • 6,858
  • 4
  • 28
  • 26
  • 1
    Why even have a var keyword? Just make it default, like python does. – Dev Aggarwal Jul 12 '18 at 18:06
  • 5
    ↑That make compiler faster, I think. – Trần Đức Tâm Dec 13 '18 at 03:17
  • 6
    Perhaps this changed with Dart 2 (I don't know Dart 1). This is a very old answer. In this case it should be updated. Also note that in Dart 2, if the `var` isn't initialized, it appears to be `dynamic` (you can do e.g. `var foo; foo = "str; foo = 1;` (or of type Object?) this would be worth to clarify. – User Feb 20 '19 at 12:42
  • 3
    He didn't even ask about final or const.. How is this the acceptable answer??? – Daniel Vilela Aug 28 '20 at 20:45
  • 1
    This answer is not responding to the question. How it is accepted? Where is the difference between var and dynamic types? The question is not about final vs const. – Davoud Aug 09 '21 at 09:47
  • @DevAggarwal http://craftinginterpreters.com/statements-and-state.html#design-note (sorry for dumping to old discussion) – Drdilyor Sep 23 '21 at 16:35
  • 1
    @DevAggarwal Not having a "var" keyword is one of the biggest issues in Python. It's sometimes extremely hard to figure out where a variable is first introduced and what it's scope is. – Markus Meskanen Oct 26 '21 at 13:50
  • 3
    This answer doesn't reflect the question – Muhammad Afzal Jan 20 '22 at 07:00
  • @JohnEvans: const requires a constant assignment... Could be this not updated?: https://dart-lang.github.io/linter/lints/unnecessary_const.html – Mau Di Bert Jan 27 '22 at 20:10
  • 1
    Please note that **If a variable is declared as a dynamic, its type can change over time**. **If you declare variable as a var, once assigned type can not change**. **BUT, if you state a var without initializing, it becomes a dynamic**. – Muhammad Afzal Aug 01 '22 at 04:53
99

dynamic: can change TYPE of the variable, & can change VALUE of the variable later in code.

var: can't change TYPE of the variable, but can change VALUE of the variable later in code.

final: can't change TYPE of the variable, & can't change VALUE of the variable later in code.

dynamic v = 123;   // v is of type int.
v = 456;           // changing value of v from 123 to 456.
v = 'abc';         // changing type of v from int to String.

var v = 123;       // v is of type int.
v = 456;           // changing value of v from 123 to 456.
v = 'abc';         // ERROR: can't change type of v from int to String.

final v = 123;       // v is of type int.
v = 456;           // ERROR: can't change value of v from 123 to 456.
v = 'abc';         // ERROR: can't change type of v from int to String.
Mimina
  • 2,603
  • 2
  • 29
  • 21
  • 23
    only if you initialize the var v. Without the initialization, var v is same as dynamic v – Ashwin Prabhu Mar 11 '20 at 11:07
  • 1
    case#2 The uninitialized variables declared with `var` keyword can only change its type like `var a;` but `var a=123;` can't change its type, it'll be integer forever. – Muhammad Afzal Jan 20 '22 at 07:31
74

try this in DartPad:

void main() {
  dynamic x = 'hal';
  x = 123;
  print(x);
  var a = 'hal';
  a = 123;
  print(a);
}

you can change the type of x, but not a.

rough
  • 741
  • 5
  • 5
  • 14
    only if you assign to a var. You can always do: var a; a="hi"; a=123; that is legal. – Ashwin Prabhu Mar 11 '20 at 11:06
  • 3
    @AshwinPrabhu yes because when we do `var a;` then `a` is a type of `dynamic` which means we can assign any type `int` or `double` because `dynamic` is a type underlying all dart objects – Muhammad Afzal Jan 20 '22 at 04:23
17

var, like final, is used to declare a variable. It is not a type at all.

Dart is smart enough to know the exact type in most situations. For example, the following two statements are equivalent:

String a = "abc"; // type of variable is String
var a = "abc";    // a simple and equivalent (and also recommended) way
                  // to declare a variable for string types

On the other hand, dynamic is a special type indicating it can be any type (aka class). For example, by casting an object to dynamic, you can invoke any method (assuming there is one).

(foo as dynamic).whatever(); //valid. compiler won't check if whatever() exists
(foo as var).whatever(); //illegal. var is not a type
Tom Yeh
  • 1,987
  • 2
  • 15
  • 23
  • 4
    Technically, the first example shows two statements that are not equivalent. `var a` creates a variable that is type Dynamic. `String a` creates a variable that is type String. The Dart Editor may perform additional type inference, which in this case it does, but remember this is behavior above and beyond the spec. – Seth Ladd Sep 17 '12 at 17:45
  • 2
    @SethLadd var a = "some string"; does not create a variable with dynamic type, because of the assignment operator, a will have a fixed type of String (in this example). – George 2.0 Hope Mar 27 '20 at 08:21
  • 1
    @SethLadd in the second case `var a="abc"` `a` is not a type of dynamic. It's a String type variable. `var a;` in this particular case, `a` is a type of dynamic when we don't initialize the variable. – Muhammad Afzal Jan 20 '22 at 04:19
14
var a ;
a = 123;
print(a is int);
print(a);
a = 'hal';
print(a is String);

When defined without initial value, var is dynamic

var b = 321;
print(b is int);
print(b);
//b = 'hal'; //error
print(b is String);

When defined with initial value, var is int in this case.

John Wang
  • 318
  • 3
  • 6
8

Looking at the previous answers I hope this can clarify/summarize everything:

There are the keywords var, final, and const. These are to declare a variable (to indicate its existence) (Side note: Declaration vs Initialization)

Then there are types like String, int, List, dynamic, etc. (The type indicates what kind of value the variable should hold, this is for type safety)

Usually, we declare a variable by explicitly stating its type:

String a; // a is now a String type
int b; // b is now an int type

But we can also use the var keyword. By default, this sets the type of the variable to whatever it is initialized with. (This is called type inference)

var a = "hello"; // a is now a String type
var b = 5; // b is now an int type

Now what happens when you try to declare a variable with the var keyword, but don't initialize a value? How is it supposed to infer a type? Well, there is also a type called dynamic. This is different than the usual String or int in the sense that it allows for the variable to be assigned a value of any type (Usually there will be an error).

String a = "hello"; // a is now a String type
// var a = "hello"; // Alternative way; same as the line above because its type is inferred to be String
a = 5 // error: A value of type 'int' can't be assigned to a variable of type 'String'

dynamic b; // b is now a dynamic type
b = "hello"; // still a dynamic type, but now its value is of type String  (You can use b.runtimeType to check)
b = 5; // dynamic type, but now its value is of type int

So to address the original confusion regarding the quote from the article,

As you might know, dynamic (as it is now called) is the stand-in type when a static type annotation is not provided.

It just means that if you don't explicitly state its type (you use var to declare a variable) and do so without initialization, it simply infers its type as dynamic:

var b; // b is now a dynamic type, the following will not have any errors.
b = "hello";
b = 5; 
b = true;

Other notes:

  • Not sure why people started talking about final and const, but I think the accepted answer here explains it well if you want to know more.

  • dynamic a; and var a; is effectively the same: They both declare a variable of dynamic type.

  • Two ways of checking the type of a variable is using the is operator and using .runtimeType which works differently. See the following example:

    dynamic b; // b is now a dynamic type, no value
    print(b is dynamic); // true
    print(b is Null); // true
    print(b is String); // false
    print(b is int); // false
    print(b.runtimeType); // Null
    
    b = "hello"; // dynamic type, String value
    print(b is dynamic); // true
    print(b is Null); // false
    print(b is String); // true
    print(b is int); // false
    print(b.runtimeType); // String
    
    b = 5; // dynamic type, int value
    print(b is dynamic); // true
    print(b is Null); // false
    print(b is String); // false
    print(b is int); // true
    print(b.runtimeType); // int
    
Milo Legends
  • 81
  • 3
  • 2
  • I don't fully agree that the type of a `dynamic` variable is `dynamic`. As you show in your last block of code, when checking the typ it is both `dynamic` and whatever type was assigned to it last. And since `runtimeType` gives you `String`, `int` or whatever, one could even argue that there are more signs pointing to the type being `String`/`int` than `dynamic` at the moment of testing it. But of course it is also still `dynamic`, because you can assign some other type to it. So in conclusion, it can be both `dynamic` and whatever type it holds at the same time, depending on how you check it. – Magnus Jan 20 '22 at 07:34
  • @Magnus The distinction shown is between the type of a *variable*, and the type of a *value*. A variable's type defines *the allowed range of values it can hold*, which might be "Foo or any subtype of Foo"; but any given value is considered to be of a single type. So the type of the variable `b` remains `dynamic` - it never loses its ability to hold any type; but at any given moment, it holds a value of some more specific type. – IMSoP Apr 30 '23 at 10:25
7

To clarify some of the previous answers, when you're declaring a variable as dynamic, it's type changes depending on what you assign to it. When you're declaring a var, the type is set once it's assigned something, and it cannot be changed after that.

For example, the following code:

dynamic foo = 'foo';
print('foo is ${foo.runtimeType} ($foo)');
foo = 123;
print('foo is ${foo.runtimeType} ($foo)');

will return the following result when run in DartPad:

foo is String (foo)
foo is int (123)

But the following code won't even compile:

var bar = 'bar';
print('bar is ${bar.runtimeType} ($bar)');
bar = 123; // <-- Won't compile, because bar is a String
print('bar is ${bar.runtimeType} ($bar)');

Long story short - use dynamic if you want a non-typed variable, use var when you want a typed variable with whatever type you assign to it.

Magnus
  • 17,157
  • 19
  • 104
  • 189
  • 1
    if we don't assign a value to a variable, `var a;`, then that variable automatically belongs to `dynamic` we don't have to explicitly use `dynamic` keyword – Muhammad Afzal Jan 20 '22 at 04:30
  • As noted in a reply above, the variable doesn't *change* its type - that would imply that once you assigned a string value, assigning an int value would no longer be possible. The type of the variable remains `dynamic`, meaning "can accept values of any type". – IMSoP Apr 30 '23 at 10:29
3

One of aspect than can consider in comparison dynamic vs var is taking into account behavior when using var declaration with initialization at the same time there is not possibility to change type which in case of dynamic is.

But dynamic vs var is not the question what I would ask. I would ask more what is difference between dynamic vs Object.

Here is a DO annotate with Object instead of dynamic to indicate any object is allowed.

It is hard to feel it at the beginning, but dynamic I would relate to generic type argument.

MagGGG
  • 19,198
  • 2
  • 29
  • 30
  • It seems the particular guidance linked to is no longer on the page. Where does that leave us with `Object` vs `dynamic`? – ubiquibacon Nov 14 '22 at 04:22
3

Both in dynamic and var,the variable can hold data of any data type, i.e., int , float,string,etc

If a variable is declared as a dynamic and if even initialised, its type can change over time.Try this code in https://dartpad.dev/

void main() {
  dynamic x = 'abc';
  x = 12345;
  print(x);

}

If you declare variable as a var, once assigned type can not change.

void main() {
  var x = 'abc';
  x = 12345;
  print(x);
}

The above code will result in the error stating that A value of type 'int' can't be assigned to a variable of type 'String' - line 3

BUT, if you state a var without initializing, it becomes a dynamic:

void main() {
  var x ;
  x = 'abc';
  x=12345;
  print(x);
}
chethanv77777
  • 480
  • 9
  • 18
1

A dynamic variable can change his type and a var type can't be changed.

For example :

var myVar = 'hello';
dynamic myDynamicVar = 'hello';
myVar = 123; // not possible
myDynamicVar = 123; // possible
Jéwôm'
  • 3,753
  • 5
  • 40
  • 73
0

dynamic is a data type that indicates all data types in dart

var is a variable declaration way like "final" that takes the data type of its value

0

If you use var you can't change the data type of the variable. But if you use dynamic you can change it freely. for ex.

dynamic x = 12; // type: integer
x= "Hello world"; // type: string

This will work with no issues if you do the same using var instead of dynamic you will get an error since you can't change the data type because it is automatically assigned to the variable when initialized.

0

dynamic: can change the TYPE of the variable, & can change the VALUE of the variable later in the code.

var: can't change the TYPE of the variable, but can change the VALUE of the variable later in code

zex_rectooor
  • 692
  • 7
  • 26
0
  • var declares a variable with an unspecified type, allowing its type to be inferred from the variable's initializer. If there is no initializer to infer a type from, then it is equivalent to declaring that variable with dynamic.

  • dynamic simply disables static type-checking for that variable. For example, attempting to call non-existent methods on it will be caught only when the code is executed at runtime instead of at compilation-time.

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
0

Var is not a type!

Var is just a keyword used to declare a mutable variable. You use var when you want the compiler to infer the type of that declared variable.

var x = "123"; 
// Compiler is smart enough to understand you want x to has String type
// x variable is String then.

Dynamic is a special type in Dart, it just simply disables static type-checking for that variable. Means compiler won't care about the type of the dynamic variable, use it as your own risk.

dynamic x = 12; 
x.length() // -> Exception thrown at runtime
// Compile successfully, but throw exception at runtime 
// since length() is a function of String type.
Hoang Nguyen Huu
  • 1,202
  • 17
  • 17