avatarCrizant Lai

Summary

The web content discusses the enhancements to enums in Dart 2.17 with the release of Flutter 3, emphasizing the benefits of using enums for type safety and the new capabilities that allow enums to carry values and behaviors.

Abstract

The article delves into the concept of enums (enumerated types) in the context of Flutter 3 and Dart 2.17, highlighting the significant improvements made to enums. It explains the traditional use of enums as a set of named constants and illustrates how enums in Dart have evolved to include additional data and functionality, thus reducing boilerplate code and minimizing errors. The author provides a practical example of a smart lightbulb interface to demonstrate how the new "enhanced enums" feature simplifies the codebase, ensures type safety, and facilitates easier maintenance and scalability when adding new states or behaviors. The article concludes by advocating for the adoption of enums, particularly the new enhanced enums, to improve code quality and readability in software development.

Opinions

  • The author believes that enums are underutilized and should be used more frequently to improve code safety and readability.
  • The author suggests that the previous workaround for enums in Dart 2.12, which involved creating a class to mimic enum behavior, was suboptimal and error-prone.
  • The new enhanced enums feature in Dart 2.17 is praised for reducing the need for repetitive code updates and for making the code more elegant and less error-prone.
  • The author implies that the enhanced enums feature is a significant step forward for the Dart language, making it more powerful and developer-friendly.
  • There is an implicit opinion that developers should follow best practices, such as using enums, to prevent runtime exceptions and to write more maintainable code.
  • The author encourages readers to engage with the content by following their profile for more insights and updates on Flutter development, indicating a desire to build a community or readership around their expertise.
Photo by Daniele Franchi on Unsplash

Flutter 3: What are enums and what is new about it

Let’s continue our Flutter 3 series. Enums have got a new power in Flutter 3/Dart 2.17; in this article, I will talk about what enum is and its new feature in Flutter 3.

What’s Enum

Enum is the short form of “Enumerated type”, a set of named constants where all possible values are declared. Enum is not a unique feature of the Dart language but exists in most modern languages.

For example, if I’m going to develop a programmable interface for a smart lightbulb, I may do this:

const int LIGHT_BULB_STATUS_ON = 1;
const int LIGHT_BULB_STATUS_OFF = 0;

Then I will define a function to set the status of the lightbulb to on or off:

void setStatus(int status) {
  // ...
}
// Usage:
setStatus(LIGHT_BULB_STATUS_ON);

This seems fine but one day a junior employee is adding new features to the codebase, and he sees that the setStatus function takes an integer parameter, then he somehow passed -1 to it, causing a runtime exception:

setStatus(-1);

It is not a good practice that he didn’t read through the codebase before doing any modification, but if the codebase is very large, who wants to read it? Is there a way to let us find the problem even in the static analysis, without running the code? Enums to the rescue!

First, we define an enum class:

enum LightBulbStatus {
  on,
  off,
}

Then the setStatus function becomes:

void setStatus(LightBulbStatus status) {
  // ...
}
// Usage:
setStatus(LightBulbStatus.on);

Now the function takes a value of the enum LightBulbStatus, which is on or off only. This has two advantages:

  1. It restricts the parameter to the values declared in the enum, passing other values to it would give an error, and the error can be found by editor plugins.
  2. It prevents others from passing direct values to the function, e.g. setStatus(0), which ensures the readability.

Therefore, you should always use enums when possible.

A week later, the hardware department came and said, the lower level of the interface(written in C) takes 1 or 0 to indicate on or off, and we need to pass an integer to it. What should I do?

Some of you may do this:

void setStatus(LightBulbStatus status) async {
  if (status == LightBulbStatus.on) {
    await channel.invokeMethod('setStatus', 1);
  } else {
    await channel.invokeMethod('setStatus', 0);
  }
}

This seems fine but if later we want to add an extra status standby(2), we need to update both the LightBulbStatus class and the setStatus method again, which is time-consuming and error-prone.

Enums in Dart 2.12

Unfortunately in Flutter 2/Dart 2.12, enums can’t carry any values, so we had to use a class to pretend an enum class:

class LightBulbStatus {
  final int value;
  // A private constructor to prevent instantiation from outside
  const LightBulbStatus._(this.value);
  
  // declare as constants so that we can use the `==` operator
  // to compare them or use them in `switch` cases
  static const on = LightBulbStatus._(1);
  static const off = LightBulbStatus._(0);
  
  // add a `values` getter so that we can use `LightBulbStatus.values` to 
  // get all possible values just like an enum class
  static List<LightBulbStatus> get values => [on, off];
}

Luckily the usage didn’t change so much:

void setStatus(LightBulbStatus status) async {
  // the `value` of the status, which is an integer,
  // is passed to the platform channel
  await channel.invokeMethod('setStatus', status.value);
}
// Usage:
setStatus(LightBulbStatus.on);

This is just a workaround, note that besides the values getter, we need to implement ourselves if we want to use the .index and .name property just like normal enums.

Enum’s new power

In Flutter 3/Dart 2.17, there’s a new feature called “Enhanced enums”, which lets us add fields/methods to enums, so the LightBuildStatus class can be simplified to:

// enhanced enum is more like a constant class
enum LightBulbStatus {
  on(1),
  off(0);
  
  // can add more properties or getters/methods if needed
  final int value;
  
  // can use named parameters if you want
  const LightBulbStatus(this.value);
}

Later if we want to add another status standby, just add one line to the LightBuildStatus class and it’s done:

// enhanced enum is more like a constant class
enum LightBulbStatus {
  on(1),
  standby(2),
  off(0);
  
  // can add more properties or getters/methods if needed
  final int value;
  
  // can use named parameters if you want
  const LightBulbStatus(this.value);
}

By using this feature, boilerplates are reduced and hence human mistakes. The code is more elegant, and we don’t have to update the setStatus function again, isn’t it amazing?

Conclusion

In this article, we have covered what enums are and why should we use them. We have also talked about the usage of enhanced enums, which is a new feature of Flutter 3/Dart 2.17. Please generously hold the clap button if this article helped you; follow my profile if you want to see more news/tricks of Flutter. See you in the next one, cheers~

Flutter
Dart
Programming
Enum
Recommended from ReadMedium