Generic Methods
Part of the Object Oriented Programming section of Coddy's Dart journey — lesson 66 of 110.
Just as classes can be generic, individual methods can also have their own type parameters. This is useful when you need a flexible method without making the entire class generic.
A generic method declares its type parameter before the return type:
T findFirst<T>(List<T> items) {
return items.first;
}
void main() {
var firstNumber = findFirst<int>([1, 2, 3]);
var firstWord = findFirst<String>(['hello', 'world']);
print(firstNumber); // 1
print(firstWord); // hello
}Dart can often infer the type from the arguments, so you don't always need to specify it explicitly:
var result = findFirst([10, 20, 30]); // Dart infers intGeneric methods are particularly useful inside classes when only certain operations need type flexibility:
class Printer {
void printItem<T>(T item) {
print('Printing: $item');
}
List<T> duplicate<T>(T item, int count) {
return List.filled(count, item);
}
}
void main() {
var printer = Printer();
printer.printItem<String>('Hello');
printer.printItem(42); // Type inferred as int
var copies = printer.duplicate('Hi', 3);
print(copies); // [Hi, Hi, Hi]
}Generic methods give you fine-grained control over type safety at the method level, keeping your classes simpler while still benefiting from compile-time type checking.
Challenge
EasyLet's build a data transformation utility that showcases the power of generic methods. You'll create a Transformer class with methods that can work with any type, giving you flexibility without making the entire class generic.
You'll organize your code into two files:
transformer.dart: Create aTransformerclass with these generic methods:T getFirst<T>(List<T> items)- returns the first element from a listT getLast<T>(List<T> items)- returns the last element from a listList<T> repeat<T>(T item, int times)- creates a list containing the item repeated the specified number of timesvoid printPair<A, B>(A first, B second)- prints two values in the formatPair: [first] and [second]
main.dart: Import your transformer file and demonstrate each generic method with different types:- Create a
Transformerinstance - Use
getFirston[10, 20, 30]and print the result - Use
getFirston['apple', 'banana', 'cherry']and print the result - Use
getLaston[1.5, 2.5, 3.5]and print the result - Use
repeatto create a list of'Hi'repeated4times and print the result - Use
repeatto create a list of7repeated3times and print the result - Use
printPairwith'Name'and42 - Use
printPairwith100andtrue
- Create a
Notice how each method declares its own type parameter(s), allowing the same Transformer object to work with integers, strings, doubles, and booleans - all with full type safety. The printPair method demonstrates using two type parameters in a single method.
Expected output:
10
apple
3.5
[Hi, Hi, Hi, Hi]
[7, 7, 7]
Pair: Name and 42
Pair: 100 and trueCheat sheet
Generic methods declare type parameters before the return type, allowing individual methods to be flexible without making the entire class generic:
T findFirst<T>(List<T> items) {
return items.first;
}Dart can infer the type from arguments, so explicit type specification is optional:
var result = findFirst([10, 20, 30]); // Dart infers intGeneric methods can be used inside non-generic classes:
class Printer {
void printItem<T>(T item) {
print('Printing: $item');
}
List<T> duplicate<T>(T item, int count) {
return List.filled(count, item);
}
}Methods can declare multiple type parameters:
void printPair<A, B>(A first, B second) {
print('Pair: $first and $second');
}Try it yourself
import 'transformer.dart';
void main() {
// Create a Transformer instance
var transformer = Transformer();
// TODO: Use getFirst on [10, 20, 30] and print the result
// TODO: Use getFirst on ['apple', 'banana', 'cherry'] and print the result
// TODO: Use getLast on [1.5, 2.5, 3.5] and print the result
// TODO: Use repeat to create a list of 'Hi' repeated 4 times and print it
// TODO: Use repeat to create a list of 7 repeated 3 times and print it
// TODO: Use printPair with 'Name' and 42
// TODO: Use printPair with 100 and true
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesLibraries & ImportsIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsInstance VariablesConstructor BasicsRecap - Simple Calculator4Null Safety
Intro to Null SafetyNullable vs Non-NullableThe ? and ! OperatorsLate Keyword & Null SafetyNull-Aware OperatorsNull Safety in ClassesRecap - User Profile System7Abstract Classes & Interfaces
Abstract ClassesAbstract MethodsInterfaces in DartImplicit InterfacesImplementing vs ExtendingMultiple InterfacesRecap - Shape Calculator10Collections & Generics
List, Set, Map OverviewType-Safe CollectionsGeneric ClassesGeneric MethodsGeneric ConstraintsIterable & IteratorRecap - Generic Storage13Advanced OOP Concepts
Composition vs InheritanceExtension MethodsCallable ClassesSealed Classes (Dart 3)Records (Dart 3)Patterns & Matching (3.0)Enums with Methods16Project: Library Management
Project OverviewBook and User Classes2Constructors in Dart
Default ConstructorNamed ConstructorsInitializer ListsConstant ConstructorsFactory ConstructorsRedirecting ConstructorsRecap - Shape Builder5Encapsulation
Public vs Private MembersThe _ Prefix ConventionLibrary-Level PrivacyGetters & Setters DepthInformation HidingRecap - Student Records8Mixins
Introduction to MixinsCreating MixinsUsing Multiple Mixinson Keyword in MixinsMixin vs InheritanceMixin vs InterfaceRecap - Animal System11Special Methods
toString() OverridehashCode & == OverrideComparable Interfacecall() MethodnoSuchMethod OverrideRecap - Custom Collection14Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy Pattern3Class Properties
Instance vs Static MembersFinal & Const FieldsLate VariablesStatic Methods & FieldsGetters and SettersRecap - Bank Account Manager6Inheritance
Basic InheritanceThe super KeywordMethod OverridingThe @override AnnotationThe final Class KeywordConstructors & InheritanceRecap - Employee Hierarchy9Polymorphism
Polymorphism BasicsPolymorphism via InterfacesRuntime Type CheckingThe is & as OperatorsCovariant KeywordRecap - Payment Processor