Menu
Coddy logo textTech

Generic Constraints

Part of the Object Oriented Programming section of Coddy's Dart journey — lesson 67 of 110.

Sometimes you need a generic type to have certain capabilities. For example, if you want to compare items or access specific properties, an unrestricted T won't guarantee those features exist. Generic constraints let you restrict type parameters to specific types or their subclasses.

Use the extends keyword to constrain a type parameter:

class NumberBox<T extends num> {
  T value;
  
  NumberBox(this.value);
  
  T doubled() => (value * 2) as T;
}

void main() {
  var intBox = NumberBox<int>(5);
  var doubleBox = NumberBox<double>(3.5);
  
  print(intBox.doubled());    // 10
  print(doubleBox.doubled()); // 7.0
  
  // var stringBox = NumberBox<String>('hi');  // Error!
}

Because T extends num, the compiler knows value supports numeric operations like multiplication. Without this constraint, calling value * 2 would fail.

Constraints work with your own class hierarchies too:

abstract class Animal {
  String get name;
}

class Dog extends Animal {
  String get name => 'Dog';
}

class Shelter<T extends Animal> {
  List<T> animals = [];
  
  void add(T animal) => animals.add(animal);
  
  void printNames() {
    for (var animal in animals) {
      print(animal.name);  // Safe: T guarantees 'name' exists
    }
  }
}

Generic constraints combine the flexibility of generics with the safety of knowing what operations are available on your type.

challenge icon

Challenge

Easy

Let's build a statistics calculator that only works with numeric types! You'll create a generic class with a constraint that ensures it can only be used with numbers, allowing you to safely perform mathematical operations on the stored values.

You'll organize your code into two files:

  • stats.dart: Create a generic Stats<T extends num> class that manages a list of numeric values:
    • A List<T> called values to store the numbers
    • A constructor that initializes the list with provided values
    • A method sum() that returns the sum of all values as a num
    • A method min() that returns the smallest value as T
    • A method max() that returns the largest value as T
    • A method printStats() that displays the statistics in a formatted way
  • main.dart: Import your stats file and demonstrate the constrained generic class with different numeric types:
    • Create a Stats<int> with values [10, 25, 5, 30, 15] and call printStats()
    • Print an empty line
    • Create a Stats<double> with values [3.5, 1.2, 4.8, 2.1] and call printStats()

The printStats() method should output three lines showing the sum, minimum, and maximum values. Because T extends num, you can safely use comparison operators and arithmetic operations on the values - something that wouldn't be possible with an unconstrained generic type.

Expected output:

Sum: 85
Min: 5
Max: 30

Sum: 11.6
Min: 1.2
Max: 4.8

Cheat sheet

Generic constraints restrict type parameters to specific types or their subclasses using the extends keyword:

class NumberBox<T extends num> {
  T value;
  
  NumberBox(this.value);
  
  T doubled() => (value * 2) as T;
}

With T extends num, the compiler knows value supports numeric operations like multiplication.

Constraints also work with custom class hierarchies:

abstract class Animal {
  String get name;
}

class Shelter<T extends Animal> {
  List<T> animals = [];
  
  void printNames() {
    for (var animal in animals) {
      print(animal.name);  // Safe: T guarantees 'name' exists
    }
  }
}

Generic constraints provide flexibility while ensuring type safety and available operations.

Try it yourself

import 'stats.dart';

void main() {
  // TODO: Create a Stats<int> with values [10, 25, 5, 30, 15]
  // and call printStats()
  
  // TODO: Print an empty line
  
  // TODO: Create a Stats<double> with values [3.5, 1.2, 4.8, 2.1]
  // and call printStats()
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming