DART / CHAPTER 07
Classes and validated state
IntermediateUse 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.
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);
}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