Exploring Generics in Dart
Generics in Dart enable developers to write flexible and reusable code while maintaining type safety. They allow you to define classes, methods, and interfaces with a placeholder for the data type, which can be specified when the code is used. This helps in creating collections and data structures that can work with any data type without sacrificing type safety.
Key Concepts
What are Generics?
Generics allow you to create classes and functions that can operate on different types specified as parameters. This means you can write a function or class once and reuse it with different data types.
Benefits of Using Generics
- Type Safety: Generics provide compile-time type checking, reducing runtime errors.
- Code Reusability: You can create methods and classes that work with multiple data types.
- Cleaner Code: Generics eliminate the need for casting, leading to cleaner and more readable code.
Declaring Generics
You can declare a generic class or method by using angle brackets (<T>
) to specify the type parameter.
Example of a Generic Class
class Box<T> {
T item;
Box(this.item);
T getItem() {
return item;
}
}
Using Generics
You can create instances of a generic class by specifying the type when creating the object.
Example of Using a Generic Class
void main() {
var intBox = Box<int>(123);
print(intBox.getItem()); // Output: 123
var stringBox = Box<String>('Hello');
print(stringBox.getItem()); // Output: Hello }
Generic Methods
You can also define generic methods within a class or as standalone functions.
Example of a Generic Method
T findMax<T extends Comparable>(List<T> items) {
T maxItem = items[0];
for (var item in items) {
if (item.compareTo(maxItem) > 0) {
maxItem = item;
}
}
return maxItem;
}
void main() {
var numbers = [1, 3, 5, 2, 4];
print(findMax(numbers)); // Output: 5
var words = ['apple', 'banana', 'orange'];
print(findMax(words)); // Output: orange
}
Bounded Generics
You can restrict the type of a generic parameter using bounds. For example, you can specify that a type must extend a particular class or implement a specific interface.
Example of Bounded Generics
class Animal {
void speak() {
print('Animal sound');
}
}
class Dog extends Animal {
@override void speak() {
print('Woof');
}
}
class AnimalShelter<T extends Animal> {
T animal;
AnimalShelter(this.animal);
void letAnimalSpeak() {
animal.speak();
}
}
void main() {
var dogShelter = AnimalShelter<Dog>(Dog());
dogShelter.letAnimalSpeak(); // Output: Woof
}
Conclusion
Generics are a powerful feature in Dart that enhances code reusability, type safety, and clarity. By allowing you to define classes and methods that can operate on different types, generics help create flexible and maintainable code. Understanding and utilizing generics will greatly improve your ability to write effective Dart applications, especially when dealing with collections and data structures.
PLAY QUIZ