Почему мне нужно использовать расширения в моем проекте Flutter / Dart?

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

Как использовать расширения?

Вы используете расширения, когда хотите:

  • добавить функциональность к существующему классу, но вы не можете изменить его напрямую, потому что он является частью внешнего API или библиотеки
  • добавить методы в перечисление (например, в Java)

Синтаксис:

extension ExtensionName on Object {
  Object doSomething(Object arg1) {
    var result;
    //do operations...
    return result;
  }
}

ExtensionName - это имя этого расширения, оно не является обязательным, мы делаем расширение для объекта, поэтому в этом случае мы можем использовать doSomething для любого класса Dart.

var str = 'Hello world!';
str.doSomething('arg1');

Пример # 1 - перечисление в String / перечисление из String

Проблема

Допустим, у вас есть перечисление

enum Animal { dog, cat, bird }

и вы хотите получить какой-нибудь объект Animal с сервера REST API.

Проблема, с которой я столкнулся, заключается в том, что ответ, который я получил от сервера формы, был в этой форме

{
  "animal":"dog"
}

и сервер принимает только значения, указанные выше, но форматы метода Dart toString () по умолчанию, такие как

print(Animal.dog.toString()); //prints Animal.dog

Поэтому мне нужно было другое решение, но я хотел избежать использования некоторых вспомогательных методов или добавления новых классов. К сожалению, в Dart нельзя писать методы для перечислений, как в Java, поэтому это был идеальный вариант использования для расширения.

Решение

Я создал двусторонние парсеры, чтобы легко общаться с сервером. Полный пример показан ниже.

Код объясняет сам себя, но в итоге позволяет мне легко анализировать перечисления полностью гибким способом.

Пример # 2

Проблема

Допустим, у вас есть метод REST, который принимает список идентификаторов пользователей и выполняет с ним некоторую операцию.

void deleteUsers(List<int> userIds) {
  //send to server...
}

Это обычный случай, но когда вы всегда храните пользователей в списке объектов

class User {
  int id;
  String name;
User(this.id, this.name);
}
var users = [User(1, 'Jack'), User(2, 'Emma'), User(3, 'James')];

вам нужно перебирать каждый элемент каждый раз, когда вы хотите вызвать метод, который принимает список идентификаторов в качестве параметра.

Решение

Чтобы сделать ваш код чище, вы можете создать расширение в Списке пользователей и использовать его везде, где вам нужно!

Полный код показан ниже:

Пример # 3

Проблема

Один из методов в моем API возвращал объект enum, но в форме массива int - число указывало, какое это значение перечисления.

Предположим, у нас есть перечисление из предыдущего примера.

enum Animal { dog, cat, bird }

сервер отправлял такое значение и принимал точно такую ​​же форму

{
  "animal":1
}

Решение

Расширения позволили мне упростить работу с этими числами. Все, что мне нужно было сделать, это убедиться, что порядок значений в моем перечислении точно такой же, как на сервере, поэтому числа

dog: 0, cat: 1, bird: 2

совпадают.

Пример # 4

Проблема

Простой пример: есть некоторые функции, которые вам нужно снова и снова использовать в своем коде, но на первый взгляд они кажутся слишком длинными и не очень понятными.

Решение

Я имел обыкновение расширять его, и это сэкономило мне несколько символов почти в каждом файле, что немного повлияло на удобочитаемость.

Пример # 5

Проблема

В моем приложении было много проверок, но вместо использования обычного решения - создания некоторого служебного / вспомогательного класса, я использовал расширения. Может быть, это не большая разница, но мне показалось немного проще.

Решение

Все примеры доступны на Github.