← → or space · progress saves for Continue on the roadmap
Goal
Use generic classes and methods with bounds, and recognize Repository<T> / Result<T> shapes.
Step 1 - Generic class
class Box<T> {
final T value;
Box(this.value);
}
void main() {
Box<int> a = Box(1);
Box<String> b = Box('hi');
print(a.value + 1);
print(b.value.toUpperCase());
}Step 2 - Generic method
T? firstOrNull<T>(List<T> items) {
if (items.isEmpty) return null;
return items.first;
}
void main() {
print(firstOrNull<int>([1, 2]));
print(firstOrNull(<String>[]));
}Step 3 - Bounded type parameter
T maxOf<T extends Comparable<T>>(T a, T b) {
return a.compareTo(b) >= 0 ? a : b;
}
void main() {
print(maxOf(3, 7));
print(maxOf('b', 'a'));
}Step 4 - Repository pattern
abstract class Repository<T> {
T? getById(String id);
void save(T item);
}- One interface, many storages: memory, file, API.
Step 5 - Result type (minimal)
class Result<T> {
final T? value;
final String? error;
Result.ok(this.value) : error = null;
Result.err(this.error) : value = null;
bool get isOk => error == null;
}
void main() {
Result<int> r = Result.ok(42);
if (r.isOk) print(r.value);
}- Real projects often use sealed types, unions, or packages; this is the idea in small form.
Practice tasks
- Write
Pair<A, B>withA first,B second, andPair<B, A> swap(). - Implement
InMemoryRepository<User>withMap<String, User>backinggetById/save. - Write
Result<T> map<T, U>(Result<T> r, U Function(T) f)that returnsResult.errifrfailed.