๐ŸŽ“ A1Learner
๐Ÿ”
0 of 37 lessons completed

Dart Bounded Generics

A bound limits the types a type parameter can accept. The bound is written with extends right after the type parameter.

A total for numbers only

Total accepts a list of one number type. Its sum method adds the values with +.

class Total<T extends num> {
  final List<T> values;

  Total(this.values);

  num sum() {
    num total = 0;
    for (var value in values) {
      total = total + value;
    }
    return total;
  }
}

void main() {
  print(Total<int>([10, 20]).sum());
  print(Total<double>([1.5, 2.25]).sum());
}

A bound on a function

bigger carries the bound on its own type parameter. It compares two values of the same number type.

T bigger<T extends num>(T a, T b) {
  if (a > b) {
    return a;
  }
  return b;
}

void main() {
  print(bigger(3, 8));
  print(bigger(4.5, 1.5));
}

A bound that names a class

The bound names the class Named. describe can call label on any value of type T.

class Named {
  final String name;

  Named(this.name);

  String label() {
    return name;
  }
}

class Dish extends Named {
  Dish(String name) : super(name);
}

String describe<T extends Named>(T item) {
  return item.label();
}

void main() {
  print(describe(Dish('Pasta')));
  print(describe(Dish('Rice')));
}

Breaking the bound

String is not a subtype of num. The compiler rejects the program before it can run.

class Total<T extends num> {
  final List<T> values;

  Total(this.values);

  num sum() {
    num total = 0;
    for (var value in values) {
      total = total + value;
    }
    return total;
  }
}

void main() {
  var bad = Total<String>(['a', 'b']);
  print(bad.sum());
}

Example

class Total<T extends num> {
  final List<T> values;

  Total(this.values);

  num sum() {
    num total = 0;
    for (var value in values) {
      total = total + value;
    }
    return total;
  }
}

void main() {
  var ints = Total<int>([5, 15, 40]);
  var doubles = Total<double>([2.5, 7.5]);
  print('Total: ${ints.sum()}');
  print('Total: ${doubles.sum()}');
}

Key points

  • A bound in a class reads class Total<T extends num>.
  • Only num and its subtypes int and double can fill a num bound.
  • Inside the class, a value of type T can use the num operations, such as +.
  • A generic function can carry a bound too.
  • A bound can name a plain class, and the code can then call methods of that class on values of type T.

In this example, one Total holds ints and sums to 60. The other holds doubles and sums to 10.0. The same class serves both number types because the bound admits both.

Note

a type that breaks the bound fails at compile time, before the program runs.

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท DartPad

Exercise

Which type can fill T in class Total<T extends num>?