104 lines
2.0 KiB
Markdown
104 lines
2.0 KiB
Markdown
# Generics in Dart: A Comprehensive Guide
|
|||
|
|
|
||
|
|
Generics allow you to write flexible, reusable code that can work with different types while maintaining type safety.
|
||
|
|
|
||
|
|
## 1. Generic Classes
|
||
|
|
|
||
|
|
You can create classes that work with different types by using type parameters.
|
||
|
|
|
||
|
|
### Example:
|
||
|
|
|
||
|
|
```dart
|
||
|
|
class Box<T> {
|
||
|
|
T contents;
|
||
|
|
|
||
|
|
Box(this.contents);
|
||
|
|
|
||
|
|
T getContents() {
|
||
|
|
return contents;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
var intBox = Box<int>(42);
|
||
|
|
var stringBox = Box<String>("Hello");
|
||
|
|
|
||
|
|
print(intBox.getContents()); // Prints 42
|
||
|
|
print(stringBox.getContents()); // Prints Hello
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## 2. Generic Methods
|
||
|
|
|
||
|
|
Methods can also use generics to work with different types.
|
||
|
|
|
||
|
|
### Example:
|
||
|
|
|
||
|
|
```dart
|
||
|
|
T first<T>(List<T> list) {
|
||
|
|
if (list.isEmpty) {
|
||
|
|
throw StateError("List is empty");
|
||
|
|
}
|
||
|
|
return list[0];
|
||
|
|
}
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
var numbers = [1, 2, 3];
|
||
|
|
var strings = ["a", "b", "c"];
|
||
|
|
|
||
|
|
print(first(numbers)); // Prints 1
|
||
|
|
print(first(strings)); // Prints a
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## 3. Type Bounds
|
||
|
|
|
||
|
|
You can restrict the types that can be used with a generic by using type bounds.
|
||
|
|
|
||
|
|
### Example:
|
||
|
|
|
||
|
|
```dart
|
||
|
|
class NumberBox<T extends num> {
|
||
|
|
T value;
|
||
|
|
|
||
|
|
NumberBox(this.value);
|
||
|
|
|
||
|
|
void square() {
|
||
|
|
print(value * value);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
var intBox = NumberBox<int>(5);
|
||
|
|
var doubleBox = NumberBox<double>(2.5);
|
||
|
|
|
||
|
|
intBox.square(); // Prints 25
|
||
|
|
doubleBox.square(); // Prints 6.25
|
||
|
|
|
||
|
|
// var stringBox = NumberBox<String>("Hello"); // Compile-time error
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## 4. Generic Collections
|
||
|
|
|
||
|
|
Dart's collection types are all generic.
|
||
|
|
|
||
|
|
### Example:
|
||
|
|
|
||
|
|
```dart
|
||
|
|
void main() {
|
||
|
|
List<int> numbers = [1, 2, 3];
|
||
|
|
Map<String, int> ages = {"Alice": 30, "Bob": 25};
|
||
|
|
Set<double> scores = {9.5, 8.7, 9.2};
|
||
|
|
|
||
|
|
numbers.add(4); // OK
|
||
|
|
// numbers.add("5"); // Compile-time error
|
||
|
|
|
||
|
|
print(ages["Alice"]); // Prints 30
|
||
|
|
print(scores.contains(9.2)); // Prints true
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Conclusion
|
||
|
|
|
||
|
|
Generics in Dart provide a powerful way to write reusable, type-safe code. They are extensively used in Dart's core libraries and are a fundamental concept for writing efficient and flexible Dart and Flutter applications.
|