Em uma versão recente do Dart 2.6, o idioma introduziu uma nova função, extensão estática ou métodos de extensão estática, que permite adicionar novos métodos aos tipos existentes. Por que precisamos de extensão? Como usá-los e para que servem?

1. Introdução
Para começar, o que é extensão em geral?
Extensão é um açúcar sintático que estende uma classe existente em um local diferente do módulo de declaração de classe.
Na programação, os métodos de extensão existem há muito tempo, então eles começaram a disparar. A extensão é usada ativamente em linguagens como C #, Java via Manifold, Swift, Kotlin e muitos outros.
O problema
Digamos que temos um método catchError, que é péssimo e precisa ser reescrito para uma nova função interessante. Suponha que ele use uma função de qualquer tipo como argumento, em vez de uma função estritamente digitada ou uma verificação de tipo de função, e isso ocorre porque, há oito meses, ao desenvolver essa funcionalidade, era lógico na época.
A primeira coisa que vem à mente é reescrever essa função, mas aqui nos deparamos com o problema de que isso ocorre com muita frequência no projeto, e a alteração da função levará à inoperabilidade de todo o projeto.
Bem, se a primeira opção não é para nós. adequado, por razões lógicas, posso implementar uma nova função Futura que atenda a todos os meus requisitos.
abstract class Future<T> { ... /// Catches any [error] of type [E]. Future<T> onError<E>(FutureOr<T> handleError(E error, StackTrace stack)) => this.catchError(... - ...); } ... }
e eu a chamarei assim:
Future<String> someString = ...; someString.onError((FormatException e, s) => ...).then(...);
Infelizmente, não posso adicionar esta função à classe Future. Se fizer isso, também o adicionarei à interface Future, e qualquer outra classe que implemente essa interface ficará incompleta e não será mais compilada.
Bem, outra opção é implementar uma função de terceiros que se parecerá com isso:
Future<T> onFutureError<T, E>(Future<T> source, FutureOr<T> handleError(E error, StackTrace stack)) => source.catchError(... - ...);
E a ligação dela ficaria assim:
Future<String> someString = ...; onFutureError(someString, (FormatException e, s) => ...).then(...);
Ótimo, tudo funciona! Mas é triste que tenha começado a ser terrivelmente lido. Nós usamos métodos. que são implementados dentro da classe, então eles são chamados -.doingSomething (); Este código é compreensível, eu apenas o li da esquerda para a direita e fico na minha cabeça uma sequência de eventos. O uso de uma função auxiliar torna o código complicado e menos legível.
Bem, então, posso implementar uma nova classe e permitir que os usuários agrupem sua interface antiga com funcionalidade aprimorada.
class CustomFuture<T> { CustomFuture(Future<T> future) : _wrapper = future; Future<T> _wrapper; Future<T> onError<E>(FutureOr<T> handleError(E error, StackTrace stack)) => _wrapper.catchError(...- ...); }
e a chamada terá a seguinte aparência:
Future<String> someString = ...; CustomFuture(someString).onError((FormatException e, s) => ...).then(...);
Parece ótimo!
Resolvendo um problema com extensão
Assim que pararmos de programar em pascal e retornarmos a 2019, a implementação dessa funcionalidade será reduzida para este tamanho:
extension CustomFuture <T> on Future<T> { Future<T> onError<E>( FutureOr<T> handleError(E error, StackTrace stack)) => this.catchError(...something clever...); }
e é assim que a chamada será:
Future<String> someString = ...; someString.onError((FormatException e, s) => ...).then(...);
Isso é tudo! A solução para esse problema levou apenas 5 linhas de código. Você. Você pode se perguntar que tipo de mágica é e como ela funciona.
De fato, ele se comporta da mesma maneira que uma classe de wrapper, embora na realidade seja apenas uma função
estática auxiliar. A extensão permite liberar a escrita explícita do wrapper.
Este não é um invólucro
O design da extensão funciona de maneira a parecer uma declaração de uma classe existente, mas age como se fosse um wrapper com um _wrapper particular. Mas há uma vantagem em comparação com uma classe de wrapper: acessar a própria classe diretamente, em vez de acessar a classe de wrapper _wrapper.
Esse recurso não foi criado para o bem dos recursos, mas como eu disse anteriormente, as extensões são realmente uma maneira mais conveniente de chamar funções estáticas. Isso significa que não há objeto wrapper.
Está tudo estático
Eu disse "métodos de extensão estática" acima, e fiz por uma razão!
O dardo é digitado estaticamente. O compilador conhece o tipo de cada expressão no momento da compilação; portanto, se você escrever user.age (19) e age for uma extensão, o compilador deverá descobrir qual tipo está envolvido no objeto especificado para encontrar o tipo de toda a chamada.
Que problemas podem surgir?
O exemplo mais simples de problemas com extensão é quando você possui mais de uma extensão em seu escopo. Basicamente, o vencedor é a extensão mais próxima do tipo de expressão real que você está chamando de membro, com algumas reservas.
A maneira mais fácil de resolver o problema é conectar estritamente a extensão necessária, ou você pode usá-la explicitamente:
... List list = ...; MyList(list).printlist(); SomeList(list).printlist(); ... extension MyList on List { void printlist() { print(...- ...); } } extension SomeList on List { void printlist() { print(...- ...); } }
Sumário
- A linguagem dardo possui uma ferramenta conveniente para expandir a funcionalidade existente.
- Você pode estender métodos, operadores, setters e getters, mas não campos.
- Você pode chamar métodos de extensão explicitamente ou - quando não houver conflito com um membro da interface ou outra extensão implicitamente.
- Chamadas implícitas funcionam como chamadas explícitas.
- Extensões são estáticas. Tudo sobre eles é resolvido com base em tipos estáticos.
Se a saída da extensão falhar devido a extensões conflitantes, você poderá executar um dos seguintes procedimentos:
- Aplique a extensão explicitamente.
- Importe a extensão conflitante com o prefixo, pois ela não estará disponível para chamadas implícitas.
- Não importe uma extensão conflitante.
Isso é tudo! Você pode usar a extensão em todo o seu potencial.
E, claro, links úteis:
Vibração do siteSite DartOnde posso ler mais sobre extensãoCanal de telegrama onde falo sobre as novidades do mundo da Flutter e não apenas