Dart from the ground up

Values, names and types

Holding a value under a name with var and final, the built-in types for whole numbers, decimals, text and truth, and the two kinds of division that catch people out.

Part 2 of 12

Beginner16 min readBack to Courses

A name for a value

A variable is a name for a value. var count = 3; asks Dart to store the number 3 under the name count, and to work out the type from the value on the right. After that, count can be read anywhere below the line that created it.

final says the value is set once and never again: final price = 450;. Use final by default and var only when the value really does change, because a value that cannot change is a value another reader never has to trace. Dart will not let you assign to a final variable a second time.

The built-in types

Four types cover almost everything you write. int is a whole number, double is a number with a decimal point, String is text in double quotes, and bool is either true or false. num is the wider type that both int and double fit into.

You can name the type instead of using var: final String title = "Cable";. It costs a few characters and pays you back the first time a value arrives that is not what you expected. A name in Dart is case sensitive, cannot start with a number, and is usually written in lowerCamelCase.

Two kinds of division

The forward slash always gives a double, even when the numbers divide exactly: 7 / 2 is 3.5 and 8 / 2 is 4.0. When you want only the whole part, use ~/: 7 ~/ 2 is 3. The percent sign gives the remainder: 7 % 2 is 1.

That split is the reason money is counted in whole cents in this course. Cents are ints, so the arithmetic is exact, and the decimal point is added at the moment of printing rather than during the sums.

A type is fixed when the name is made

var does not mean "no type". It means "work the type out once, here, from the value on the right". After var count = 3; the name count is an int for the rest of its life. count = "four"; is an error, not a change of type.

That fixed type is what lets the compiler help you. It knows what can be done with count, so it can point at the line where a String arrived where a number was expected — before the program runs, rather than after a wrong total is printed.

num is the exception worth knowing: it is the wider type that holds both int and double. A variable declared as num may hold 7 on one line and 2.5 on the next, which is useful when one column of a report mixes the two. Prefer the narrower type everywhere else.

Turning a value from one type into another

Text that came from somewhere else — a file, a field, a line of a table — is a String even when it looks like a number. int.parse("42") reads it as an int and double.parse("2.5") as a double. If the text is not a number, parse throws; int.tryParse answers null instead, which chapter eleven puts to work.

The other direction is a call on the value. count.toString() gives text you can join to other text, price.toDouble() widens an int, and price.round() gives the nearest int. Nothing changes in place: each call returns a new value, and the old one is untouched.

Formatting is a later step, not a conversion. toStringAsFixed(2) returns a String written the way a price is written, and it belongs on the line that prints, where the wording of the output is decided.

Names, types and the two divisions

void main() {
  var count = 2;            // can change
  final price = 450;        // set once
  final double rate = 2.5;
  final bool paid = false;

  count = count + 3;
  print(count);             // 5
  print(price ~/ 3);        // 150
  print(9 / 2);             // 4.5
  print(9 % 2);             // 1
  print(price * rate);      // 1125.0
  print("paid: " + paid.toString());
}

A var, three finals and a sum

Run it and match each printed line to the line above it. Then add a final called rateCents set to 725, print it divided by 100 with the forward slash, and print the same value with the two slashes to see what changes.

Output
Click "Run" to execute your code

Three type mistakes to expect. Assigning text to a name that was made with a number, because var fixed the type at that line. Dividing with / and expecting an int back, when / always gives a double. And joining a number to a string with +, which Dart refuses; call .toString() first or use interpolation.

Try these next

  • Declare a num, put an int in it, print it, then put a double in it and print it again.
  • Turn the text "125" into an int with int.parse, add 75, and print the total.
  • Print 2500 cents as a price with toStringAsFixed(2) and check where the decimal point lands.

Breaking cents into dollars and coins

Run it and trace one value through each step. Then change the starting cents to 987 and work out on paper what dollars, quarters, dimes and pennies should be before you run it again.

Output
Click "Run" to execute your code

When a number prints with a trailing point zero, the value is a double rather than an int. That is not a mistake in your arithmetic: it is Dart telling you which type you ended up with.

Check what you learned

One question at a time. A wrong answer explains itself — take another go.

Part 1 of 5

What does the word final promise about a value?