Photo by Fahim Muntashir on Unsplash

Extension functions. Why are they so cool? TOP 10

Slawomir Przybylski

--

Flutter is a popular open-source framework for building cross-platform mobile applications. One of the key features of Flutter is the ability to extend existing classes using extension functions. In this article, we will explore how to use extension functions in Flutter and how they can help make your code more readable and maintainable.

An extension function is a special type of function that allows you to add new functionality to an existing class without having to modify the class itself. This is done by defining a new function with the “extension” keyword followed by the class you want to extend. For example, if you want to add a new method to the String class, you can do so by defining an extension function as follows:

extension StringExtensions on String {
String repeat(int times) {
return this * times;
}
}

You can then use this new method on any instance of the String class, like so:

print("Hello".repeat(3)); // prints "HelloHelloHello"

One of the main advantages of using extension functions is that they make your code more readable. By using extension functions, you can add new methods to existing classes that make sense in the context of your application. This can help make your code more self-documenting and easier to understand.

Another advantage of extension functions is that they allow you to reuse code. For example, you can define an extension function that adds a new method to the List class, and then use that method in multiple places throughout your application. This can help reduce the amount of duplicated code in your application, making it easier to maintain.

Here is an example of an extension function for List class

extension ListExtensions<T> on List<T> {
List<T> distinctBy(Function function) {
return this.where((element) => this.where(function(element)).toList().length == 1).toList();
}
}

You can use this function as

final myList = [1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9];
print(myList.distinctBy((i)=>i%2==0)); // prints [1, 3, 5, 7, 9, 1, 3, 5, 7, 9]

Extension functions, which can’t be denied to save time, are particularly useful because programming is often a repeatable process and many projects have something in common. It is a great idea to create a list of most useful extension functions, create a github repository and keep them there.

On the other hand, you can create a Flutter package, and publish it to
pub.dev. I highly recommend doing so, as the community is the greatest thing for any programming language and we should all help each other.

Let’s take a look at more examples of extension functions

1. isNumeric(): This extension function can be added to the String class to check if a string contains only numeric characters. This can be useful for validating user input, for example.

extension StringExtensions on String {
bool isNumeric() {
if(this == null) return false;
return double.tryParse(this) != null;
}
}

2. isEmail(): This extension function can be added to the String class to check if a string is a valid email address. This can be useful for validating user input, for example.

extension StringExtensions on String {
bool isEmail() {
if(this == null) return false;
final pattern = r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
final regex = RegExp(pattern);
return regex.hasMatch(this);
}
}

3. toInt(): This extension function can be added to the String class to convert a string to an integer. This can be useful for parsing user input, for example.

extension StringExtensions on String {
int toInt() {
if(this == null) return 0;
return int.parse(this);
}
}

4. isDigit(): This extension function can be added to the String class to check if a string contains only digit characters. This can be useful for validating user input, for example.

extension StringExtensions on String {
bool isDigit() {
if(this == null) return false;
return this.split('').every((c) => c >= '0' && c <= '9');
}
}

5. isPhoneNumber(): This extension function can be added to the String class to check if a string is a valid phone number. This can be useful for validating user input, for example.

extension StringExtensions on String {
bool isPhoneNumber() {
if(this == null) return false;
final pattern = r'^(?:[+0]9)?[0-9]{10}$';
final regex = RegExp(pattern);
return regex.hasMatch(this);
}
}

6. isURL(): This extension function can be added to the String class to check if a string is a valid URL. This can be useful for validating user input, for example.

extension StringExtensions on String {
bool isURL() {
if(this == null) return false;
final pattern = r'^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$';
final regex = RegExp(pattern);
return regex.hasMatch(this);
}
}

7. toDateTime(): This extension function can be added to the String class to convert a string to a DateTime object. This can be useful for parsing user input, for example.

extension StringExtensions on String {
DateTime toDateTime() {
if(this == null) return null;
return DateTime.tryParse(this);
}
}

8. capitalize(): This extension function can be added to the String class to capitalize the first letter of a string.

extension StringExtensions on String {
String capitalize() {
if(this == null) return null;
return "${this[0].toUpperCase()}${this.substring(1)}";
}
}

9. truncate(): This extension function can be added to the String class to truncate a string to a specified number of characters, with an optional ellipsis.

extension StringExtensions on String {
String truncate({int length = 10, String ellipsis = '...'}) {
if(this == null) return null;
if(this.length <= length) return this;
return "${this.substring(0, length)}$ellipsis";
}
}

10. toTimeString(): This extension function can be added to the Duration class to convert a duration to a human-readable string.

extension DurationExtensions on Duration {
String toTimeString() {
if(this == null) return null;
String twoDigits(int n) {
if (n >= 10) return "$n";
return "0$n";
}
String twoDigitMinutes = twoDigits(inMinutes.remainder(Duration.minutesPerHour));
String twoDigitSeconds = twoDigits(inSeconds.remainder(Duration.secondsPerMinute));
return "${inHours.toString().padLeft(2,'0')}:$twoDigitMinutes:$twoDigitSeconds";
}
}

11. toColor(): This extension function can be added to the String class to convert a string to a color, this can be useful when getting user input.

extension StringExtensions on String {
Color toColor() {
if(this == null) return null;
return Color(int.parse(this.substring(1, 7), radix: 16) + 0xFF000000);
}
}

These are just a few examples of the many extension functions that can be useful in a Flutter application. By extending the built-in classes in Dart, you can add custom functionality and make your code more readable and maintainable.

In conclusion, extension functions are a powerful feature of Flutter that can help make your code more readable and maintainable. By using extension functions, you can add new functionality to existing classes in a way that makes sense in the context of your application, and reuse code throughout your application. So, It’s always a good practice to use extension functions while developing a flutter application.

--

--

Slawomir Przybylski

Highly experienced Flutter and Android developer with over 6 years of experience in the industry