DART / CHAPTER 07

Classes and validated state

Intermediate

Use constructors and library privacy to control a model.

By the end of this chapter

  • Initialize fields through constructors
  • Protect state with a private field
  • Trace shared object references

The idea

A Dart class defines fields and operations for objects. Constructor parameters can initialize fields directly, and named constructors provide meaningful alternative creation paths. A name beginning with an underscore is private to its library, not exclusively to one class. Use a getter to expose a readable value and methods to control changes that must preserve a rule.

Class variables hold references, so assigning an object to another variable creates an alias. Validation should happen before mutation so a failed operation leaves a consistent state. A constructor can reject an invalid starting value with an exception. The same invariant must then remain protected by every later modifying method; constructor checks alone are not sufficient.

Dart example
class Stock {
  int _count;
  Stock(this._count) {
    if (_count < 0) throw ArgumentError("negative count");
  }
  int get count => _count;
  bool take(int n) {
    if (n < 0 || n > _count) return false;
    _count -= n; return true;
  }
}
void main() {
  final stock = Stock(5);
  print(stock.take(2));
  print(stock.count);
}
Result
true
3

The constructor establishes nonnegative stock. take checks the request before subtracting, so successful calls preserve that rule and rejected calls change nothing.

Try it yourself

Create a class representing a bounded progress count with a read-only public getter.

Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.

CHECK YOUR UNDERSTANDING

Chapter checkpoint

Using Stock above, what count remains after Stock(3).take(4) on that object?