Generics in Dart are used to create reusable and flexible code that can work with different data types.
Generics allow you to define classes, functions, and collections that don’t depend on specific data types.
This significantly reduces code duplication, increases type safety, and makes the code more readable and maintainable.
In this article, we’ll explore Dart generics in detail.
Syntax of Generics in Dart
The basic syntax of Generics is <T> following a class, function, or collection type.
The T
inside the brackets represents a type parameter, but you can use any identifier.
Here is a simple example that describes the use of Generics with a class.
T
can be replaced by any type when the class is used, allowing the same code to work with both int and String
1 |
class SomeClass<T> {<br> T value;<br><br> SomeClass(this.value);<br><br> T getValue() => value;<br>}<br><br>void main() {<br> var someIntClass = SomeClass<int>(5);<br> print(someIntClass.getValue()); // Output: 5<br><br> var someStringClass = SomeClass<String>("Hello");<br> print(someStringClass.getValue()); // Output: Hello<br>}<br> |
Dart’s built-in collections (List, Set and Map) are generic, which means you can specify the type of elements they contain. This ensures type safety and eliminates the need for casting.
1 |
void main() {<br> List<int> intList = [1, 2, 3];<br> List<String> stringList = ["one", "two", "three"];<br><br> intList.add(4); // Works fine<br> stringList.add("four"); // Works fine<br><br> // intList.add("five"); // Compilation error<br> // stringList.add(5); // Compilation error<br>}<br> |
The compiler knows that intList can only hold int values and stringList can only hold String values
Generic Functions
Generic functions allow you to write flexible and reusable code without specifying exact data types.
1 2 3 4 5 6 7 8 9 10 11 12 |
void swap<T>(T a, T b) { T temp = a; a = b; b = temp; print('a = $a, b = $b'); } void main() { swap<int>(6, 9); // Output: a = 9, b = 6 swap<String>("Hello", "Mobikul"); // Output: a = Mobikul, b = Hello } |
The type parameter T allows the same function to work with both int and String types.
Multiple Type Parameters
Multiple type parameters are useful when creating a class or function that depends on more than one type.
1 |
class MultipleTypeParameter<T, U> {<br> T key;<br> U value;<br><br> MultipleTypeParameter(this.key, this.value);<br>}<br><br>void main() {<br> var pair1 = MultipleTypeParameter<int, String>(1, "One");<br> print("Pair1: Key = ${pair1.key}, Value = ${pair1.value}");<br><br> var pair2 = MultipleTypeParameter<String, bool>("isLoggedIn", true);<br> print("Pair2: Key = ${pair2.key}, Value = ${pair2.value}");<br>}<br> |
MultipleTypeParameter<T, U>is a generic class with two type parameters, T and U.
Why Use Generics in Dart?
- Generics helps ensure that the types you’re working with are known at compile-time, reducing the likelihood of runtime errors due to incorrect type handling.
- Generics enable you to create reusable components that work with different types without needing to rewrite the code for each new type.
- Generics make code more readable by making type dependencies explicit. Developers reading the code can immediately understand what types a function or class expects.
Conclusion
In Flutter, generics are commonly used to create flexible widgets and state management solutions.
From generic classes to functions and collections, the ability to work with different data types without sacrificing type safety makes generics a fundamental part of any Dart developer’s toolkit.
Hope you enjoyed this article.
Please check my other blogs here.
You can check the official documentation here.