Функции расширения. Почему они такие крутые? ТОП 10

Flutter — это популярный фреймворк с открытым исходным кодом для создания кроссплатформенных мобильных приложений. Одной из ключевых особенностей Flutter является возможность расширения существующих классов с помощью функций расширения. В этой статье мы рассмотрим, как использовать функции расширения во Flutter и как они могут помочь сделать ваш код более читабельным и удобным в сопровождении.

Функция расширения — это особый тип функции, который позволяет добавлять новые функции в существующий класс без необходимости изменять сам класс. Это делается путем определения новой функции с ключевым словом «расширение», за которым следует класс, который вы хотите расширить. Например, если вы хотите добавить новый метод в класс String, вы можете сделать это, определив функцию расширения следующим образом:

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

Затем вы можете использовать этот новый метод для любого экземпляра класса String, например:

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

Одним из основных преимуществ использования функций расширения является то, что они делают ваш код более читабельным. Используя функции расширения, вы можете добавлять к существующим классам новые методы, которые имеют смысл в контексте вашего приложения. Это поможет сделать код более самодокументируемым и понятным.

Еще одно преимущество функций расширения заключается в том, что они позволяют повторно использовать код. Например, вы можете определить функцию расширения, которая добавляет новый метод в класс List, а затем использовать этот метод в нескольких местах вашего приложения. Это может помочь уменьшить количество дублированного кода в вашем приложении, упрощая его обслуживание.

Вот пример функции расширения для класса List

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

Вы можете использовать эту функцию как

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]

Функции расширения, от которых нельзя отказаться, чтобы сэкономить время, особенно полезны, потому что программирование часто представляет собой повторяющийся процесс, и у многих проектов есть что-то общее. Это отличная идея создать список наиболее полезных функций расширения, создать репозиторий на github и хранить их там.

С другой стороны, вы можете создать пакет Flutter и опубликовать его на
pub.dev. Я настоятельно рекомендую это сделать, так как сообщество — это самое важное для любого языка программирования, и мы все должны помогать друг другу.

Давайте посмотрим на другие примеры функций расширения.

1. isNumeric(): эту функцию расширения можно добавить в класс String, чтобы проверить, содержит ли строка только числовые символы. Это может быть полезно, например, для проверки пользовательского ввода.

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

2. isEmail(): эту функцию расширения можно добавить в класс String, чтобы проверить, является ли строка допустимым адресом электронной почты. Это может быть полезно, например, для проверки пользовательского ввода.

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(): Эту функцию расширения можно добавить в класс String для преобразования строки в целое число. Это может быть полезно, например, для анализа пользовательского ввода.

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

4. isDigit(): эту функцию расширения можно добавить в класс String, чтобы проверить, содержит ли строка только цифровые символы. Это может быть полезно, например, для проверки пользовательского ввода.

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

5. isPhoneNumber(): Эту функцию расширения можно добавить в класс String, чтобы проверить, является ли строка допустимым номером телефона. Это может быть полезно, например, для проверки пользовательского ввода.

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(): эту функцию расширения можно добавить в класс String, чтобы проверить, является ли строка допустимым URL-адресом. Это может быть полезно, например, для проверки пользовательского ввода.

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(): эту функцию расширения можно добавить в класс String для преобразования строки в объект DateTime. Это может быть полезно, например, для анализа пользовательского ввода.

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

8. capitalize(): эта функция расширения может быть добавлена ​​к классу String, чтобы сделать первую букву строки заглавной.

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

9. truncate(): эта функция расширения может быть добавлена ​​к классу String для усечения строки до указанного количества символов с необязательным многоточием.

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(): Эту функцию расширения можно добавить в класс Duration, чтобы преобразовать продолжительность в удобочитаемую строку.

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(): Эту функцию расширения можно добавить в класс String для преобразования строки в цвет, это может быть полезно при получении пользовательского ввода.

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

Это всего лишь несколько примеров многих функций расширения, которые могут быть полезны в приложении Flutter. Расширяя встроенные классы в Dart, вы можете добавлять собственные функции и делать свой код более читабельным и удобным в сопровождении.

В заключение, функции расширения — это мощная функция Flutter, которая может помочь сделать ваш код более читабельным и удобным в сопровождении. Используя функции расширения, вы можете добавлять новые функции к существующим классам таким образом, чтобы это имело смысл в контексте вашего приложения, и повторно использовать код во всем приложении. Таким образом, всегда рекомендуется использовать функции расширения при разработке флаттер-приложения.