Lesson 7 · 7 of 20
Extension methods · Dart
Add methods and getters to int, String or List in Dart with extensions, generic ones included, without subclassing or changing those classes.

Extensions add methods and getters to types you do not own, such as int, String or List, without subclassing them or wrapping them in another class. You declare them with extension Name on Type and, inside, this is the value the member is called on.
MoneyFormat gives integers an eur getter, so 1999.eur returns 19.99 EUR. TextTools adds two helpers to String: capitalized (first letter upper case, the rest lower case) and toSlug(), which uses two regular expressions to turn a title into URL-friendly text. Notice that inside the extension you call trim() or substring() without a prefix, just as in a method of the class itself.
Stats extends Iterable<int>, so it works on lists, sets and any iterable of integers: total adds up with fold and average divides by length. Extensions combine naturally: basket.average.round().eur rounds the average and formats it with the first extension.
SafeIndex<T> is a generic extension: it works on a List of any type, and at(7) returns null instead of throwing a RangeError. Extensions are picked at compile time from the static type of the expression, so they do not work on a dynamic variable.
Code · main.dart
// Extensions add methods to types you do not own, like int or String.extension MoneyFormat on int { String get eur => '${(this / 100).toStringAsFixed(2)} EUR';}extension TextTools on String { String get capitalized => isEmpty ? this : this[0].toUpperCase() + substring(1).toLowerCase(); String toSlug() => trim() .toLowerCase() .replaceAll(RegExp(r'[^a-z0-9]+'), '-') .replaceAll(RegExp(r'^-|-$'), '');}extension Stats on Iterable<int> { int get total => fold(0, (sum, n) => sum + n); double get average => isEmpty ? 0 : total / length;}// Generic extension: works on a List of any type.extension SafeIndex<T> on List<T> { T? at(int index) => index >= 0 && index < length ? this[index] : null;}void main() { print(1999.eur); print('mADRID'.capitalized); print(' Advanced Dart: Records & Patterns! '.toSlug()); final basket = [1250, 899, 4500]; print('Total ${basket.total.eur}, average ${basket.average.round().eur}'); print('Item 1: ${basket.at(1)}, item 7: ${basket.at(7)}');}Output · dart run main.dart
19.99 EUR Madrid advanced-dart-records-patterns Total 66.49 EUR, average 22.16 EUR Item 1: 899, item 7: null
Key points
extension Name on Typeadds members to types you do not own.- Inside the extension,
thisis the value it was called on. - They can be getters, methods and even operators.
- They can be generic:
extension X<T> on List<T>. - They are chosen by static type, so
dynamicvalues miss them.
Exercise
Write an extension on String with an initials getter that returns the upper-case initials, so that 'ana belen ruiz'.initials gives ABR.