Dart Generics
Generics in Dart
Generics in Dart allow you to create classes, methods, and collections that operate on a specific data type but can be used with different data types without needing to rewrite the code. By using generics, you make your code more flexible, reusable, and type-safe. Generics are especially useful for creating collections (e.g., List
, Set
, Map
) and generic classes that work with any data type.
Why Use Generics?
- Type Safety: Generics enforce type safety, helping catch type-related errors at compile time.
- Code Reusability: Write a single implementation that works with various types.
- Clarity and Readability: Generics make it clear what types a class or function will work with, reducing ambiguity.
Basic Syntax of Generics
To declare generics, use angle brackets <>
with a type parameter. The most common type parameter name is T
(standing for "Type"), but you can use any identifier.
Examples of Generics in Dart
1. Generic Class Example: Box
A Box
class that can hold any type of item, represented by the generic type T
. The type is defined when creating an instance of the Box
class.
Explanation:
- The
Box
class is a generic class that takes a typeT
. item
is a variable of typeT
, allowing it to hold any type of data.- When creating instances of
Box
, you specify the type. ForstringBox
,T
isString
; forintBox
,T
isint
.
2. Generic Method Example
Generics can also be applied to methods, allowing a method to operate on various data types.
Explanation:
printItem
is a generic method with the type parameter<T>
.- It accepts a parameter of type
T
, allowing it to print any type of item. - The method is called with different types (
String
andint
), demonstrating its flexibility.
3. Generic Collections
Collections in Dart, such as List
, Set
, and Map
, are often used with generics to enforce type safety.
Explanation:
List<int>
specifies thatnumbers
can only hold integers.Map<String, int>
specifies thatages
is a map withString
keys andint
values.- Using generics with collections helps ensure that only the specified types are added, preventing runtime errors.
4. Generic Constraints
You can set constraints on generics to ensure they meet certain requirements. For example, you can restrict a generic type to be a subclass of a particular class.
Explanation:
AnimalShelter
is a generic class that only accepts types that are subclasses ofAnimal
, thanks to<T extends Animal>
.- The
Dog
class is a subclass ofAnimal
, soAnimalShelter<Dog>
is valid. - If you try to create
AnimalShelter<String>
, it will cause a compile-time error, ensuring type safety.
Benefits of Generics
- Reduced Code Duplication: Generics eliminate the need to write multiple versions of a class or function for different data types.
- Compile-Time Type Checking: Generics allow Dart to enforce type checks at compile time, reducing runtime errors.
- Increased Code Flexibility: Generic classes and functions are flexible and reusable across various data types, making them ideal for many applications.
Summary
Generics in Dart provide a way to create flexible, reusable, and type-safe code. By defining classes, methods, and collections with generic types, Dart allows you to work with multiple data types while enforcing type checks at compile time. Generics are especially powerful when building classes or methods that can handle different data types without sacrificing type safety.