Dart Extensions
An extension adds methods and getters to an existing type without changing that type. The added members are called on values of the type as if they were part of it.
A method and a getter on String
The extension adds shouted and bracketed to every string. The method call and the getter read both work on the word.
extension on String {
String shouted() {
return toUpperCase() + '!';
}
String get bracketed {
return '[' + this + ']';
}
}
void main() {
var word = 'dart';
print(word.shouted());
print(word.bracketed);
}An action repeated by an int
The times extension runs its action once for each count up to the receiver. The counter inside the closure grows on every run.
extension on int {
void times(void Function() action) {
for (var i = 0; i < this; i++) {
action();
}
}
}
void main() {
var count = 0;
var repeats = 3;
repeats.times(() {
count++;
print('step $count');
});
print(count);
}A generic extension on a list
second reads the item at index 1 and returns null for a shorter list. The same getter works on a list of numbers and a list of strings.
extension SecondItem<T> on List<T> {
T? get second {
if (length >= 2) {
return this[1];
}
return null;
}
}
void main() {
var numbers = [10, 20, 30];
var letters = ['a', 'b'];
var single = [7];
print(numbers.second);
print(letters.second);
print(single.second);
}Calling a named extension explicitly
StringExt is the name of the extension, and writing it around a value calls its member directly. The plain call and the explicit call print the same line.
extension StringExt on String {
String shouted() {
return toUpperCase() + '!';
}
}
void main() {
print('hi'.shouted());
print(StringExt('hi').shouted());
}Example
extension WordTools on String {
String get firstLetter {
return substring(0, 1);
}
String get lastLetter {
return substring(length - 1);
}
}
void main() {
var word = 'dart';
print(word.firstLetter);
print(word.lastLetter);
print(WordTools(word).firstLetter);
}Key points
- An extension declares the type it extends after the word on.
- Inside an extension, this refers to the value the member was called on.
- An extension can add a method and a getter to the same type.
- A generic extension on List<T> works for lists of any element type.
- A named extension can be called explicitly by writing its name around a value.
In this example, WordTools adds two getters to String. The first two prints call them on the word in the plain way. The last print calls the same extension explicitly by name and shows the same first letter.
Note
Extensions add no stored state, so an extension cannot add instance fields to a type.
Try it Yourself
Edit the code, then press Run.
Running is simulated · DartPad
Exercise
What can an extension not add to a type?