Google News
logo
Dart - Interview Questions
Explain the concept of generics in Dart.
Generics in Dart provide a way to create reusable and type-safe code by allowing classes, functions, and interfaces to operate on different types without sacrificing type safety at compile-time. Generics enable the creation of flexible and reusable code that can work with multiple data types while preserving type checks and avoiding the need for unnecessary type casting.

Here are the key concepts related to generics in Dart :

1. Generic Classes : A generic class is a class that can operate on different types of objects. It is defined by specifying one or more type parameters in angle brackets (`<>`) after the class name. Type parameters represent placeholder types that are substituted with actual types when instances of the class are created. For example:
   class Box<T> {
     T value;

     Box(this.value);
   }

   void main() {
     var box = Box<int>(42);
     print(box.value); // Output: 42
   }​

   In the example above, the `Box` class is defined with a type parameter `T`. The `Box` class can be instantiated with different types, such as `int`, `String`, or custom types. The type parameter `T` is used as the type of the `value` property.

2. Generic Functions : Similar to generic classes, Dart also allows the creation of generic functions. Generic functions can operate on multiple types by using type parameters. Type parameters for functions are also specified using angle brackets (`<>`). For example:
   T findFirst<T>(List<T> items) {
     if (items.isNotEmpty) {
       return items[0];
     }
     return null;
   }

   void main() {
     var numbers = [1, 2, 3, 4, 5];
     var firstNumber = findFirst<int>(numbers);
     print(firstNumber); // Output: 1
   }​
   In the above example, the `findFirst` function is a generic function that takes a list of type `T` and returns the first element of the list. The type parameter `T` is specified when calling the function.

3. Generic Constraints : Dart provides the ability to apply constraints on type parameters to restrict the types that can be used. This ensures that the generic code is used with compatible types. Constraints can be applied using the `extends` keyword followed by the type or interface that the type parameter must extend or implement. For example:
   class Box<T extends num> {
     T value;

     Box(this.value);
   }

   void main() {
     var box1 = Box<int>(42);   // OK, int extends num
     var box2 = Box<double>(3.14);  // OK, double extends num
     var box3 = Box<String>('hello');  // Error, String does not extend num
   }​


   In the example above, the `Box` class is constrained with the `num` type using the `extends` keyword. This means that the type parameter `T` must be a subtype of `num`. Therefore, `int` and `double` are valid types for `T`, but `String` is not.

Generics in Dart provide a powerful mechanism for writing reusable and type-safe code that can work with various types. It promotes code reusability, enhances type safety, and reduces the need for explicit type casting. By utilizing generics effectively, you can write more flexible and maintainable code in Dart.
Advertisement