Declaring Type-Safe Collections
Learn about declaring type-safe collections using generics.
We'll cover the following
Declaring Type-Safe Collections
In the previous lesson, you learned that Dart allows for storing different types of data in one collection. But a problem could arise if Dart is unable to handle all types of data in a given collection.
In this lesson, you will learn to declare type-safe collections to solve this problem.
To ensure type safety, the angular brackets <>
with data type enclosed, are used to declare the collection of the given data type. Type safety ensures that only one type of data can be stored in one collection.
Syntax:
CollectionType <dataType> identifier = CollectionType <dataType>();
Example:
List<int> numbers = List<int>();
Generics are parameterized. They use type variable notations to restrict the type of data.
We can understand this with the help of an example. Assume that you have three classes:
Product
Class: This class represents a grocery item. It hasid
,title
, andprice
members to define a product.
//A class for grocery product
class Product {
final int id;
final double price;
final String title;
Product(this.id, this.price, this.title);
@override
String toString() {
return "Price of ${this.title} is \$${this.price}";
}
}
Inventory
Class: This class holds information about the inventory of a product. Theamount
of typeint
represents the number of items available for a product.
//A class for the product's inventory
class Inventory {
final int amount;
Inventory(this.amount);
@override
String toString() {
return "Inventory amount: $amount";
}
}
Store
Class: This class uses aHashMap
to keep track of products and their inventories. It also has a method to update the inventory and print all products along with their inventory information. We will use parameterized generics to implement theStore
class.
Generics are represented in two ways:
- Single Letter Names
- Descriptive Words
Single Letter Names
Typically, parameters for generics are represented using single-letter names. Some typically used single letter names are:
- E: The letter
E
is used to represent the element type in a collection like List. - K: The letter
K
is used to represent the key type in associative collections like Map. - V: The letter
V
is used to represent the value type in associative collections like Map. - R: The letter
R
is used to represent the return type of a method or function.
You can also use a single letter of your choice. We will use the letter P
for Product
and the letter I
for Inventory
. Check out the Store
class implementation with single-letter name parameters.
The Store
accepts two parameters as single letter names: P
& I
.
//Custom type variables- Single letter
class Store<P, I> {
final HashMap<P, I> catalog = HashMap<P, I>();
List<P> get products => catalog.keys.toList();
void updateInventory(P product, I inventory) {
catalog[product] = inventory;
}
void printProducts() {
catalog.keys.forEach(
(product) => print("Product: $product, " + catalog[product].toString()),
);
}
}
The main() Method:
In the main()
method, we create two instances of Product
: milk
and bread
. These two products are added to the store1
inventory. Then, the printProducts()
method prints the product name and number of items in the inventory.
void main() {
Product milk = Product(1, 5.99, "Milk");
Product bread = Product(2, 4.50, "Bread");
//Using single letter names for Generics
Store<Product, Inventory> store1 = Store<Product, Inventory>();
store1.updateInventory(milk, Inventory(20));
store1.updateInventory(bread, Inventory(15));
store1.printProducts();
}
Output:
Product: Price of Milk is $5.99, Inventory amount: 20
Product: Price of Bread is $4.5, Inventory amount: 15
Try it yourself
Let’s put together the single-letter name generics implementation. Run the code by clicking the ‘Run’ button.
Get hands-on with 1400+ tech skills courses.