Function

No Dart, funções também são objetos — isso diferencia um pouco das outras linguagens de programação.

Funções são objetos de primeira classe

Dart é uma linguagem totalmente orientada a objetos: as próprias funções são objetos, com o tipo Function.

Elas podem ser atribuídas a variáveis e passadas como argumentos para outras funções;

Instâncias de classe podem ser invocadas diretamente como se fossem funções

1 Definição padrão de função

// Declaração completa com anotações de tipo de retorno e parâmetros
bool isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}Code language: JavaScript (javascript)

Exemplo completo

// Tabela de correspondência dos números atômicos dos gases nobres
final Map<int, String> _nobleGases = {
  2: 'He',
  10: 'Ne',
  18: 'Ar',
  36: 'Kr',
  54: 'Xe',
  86: 'Rn',
};

// Declaração completa com tipo de retorno e tipos de parâmetros
// O tipo int não aceita null; use int? para aceitar parâmetros anuláveis
bool isNoble(int? atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}

void main() {
  print(isNoble(null));       // null não é uma chave do mapa → false
  print(isNoble(2));          // Corresponde a um gás nobre → true
  print(isNoble(9));          // Sem correspondência → false
  print(isNoble(86));         // Corresponde a um gás nobre → true
}Code language: PHP (php)
false
true
false
trueCode language: JavaScript (javascript)

2 Omitir anotações de tipo

O guia de estilo Effective Dart recomenda anotações de tipo explícitas e completas para APIs públicas visíveis externamente.

Você pode omitir anotações de tipo em funções privadas internas

Exemplo


final Map&lt;int, String> _nobleGases = {
  2: 'He',
  10: 'Ne',
  18: 'Ar',
  36: 'Kr',
  54: 'Xe',
  86: 'Rn',
};


isNoble(atomicNumber) {
  return _nobleGases&#91;atomicNumber] != null;
}

void main() {
  print(isNoble(null));       // null não é uma chave do mapa → false
  print(isNoble(2));          // Corresponde a um gás nobre → true
  print(isNoble(9));          // Sem correspondência → false
  print(isNoble(86));         // Corresponde a um gás nobre → true
}

Code language: PHP (php)

No exemplo acima, a função isNoble omite o tipo de retorno bool e o tipo de parâmetro int?, mas funciona normalmente.

Quando você não escreve tipos, Dart realiza uma inferência de tipo automática:

  • Parâmetro atomicNumber: Sem tipo explícito → inferido como dynamic (tipo dinâmico, aceita qualquer valor: números, strings, null)
  • Valor de retorno: Sem anotação de tipo no início → Dart deduz que o tipo de retorno é bool a partir da expressão após return, sem escrevê-lo no código
Por que APIs públicas devem obrigatoriamente ter tipos explícitos?

Legibilidade: Desenvolvedores que chamam sua função veem imediatamente os tipos de entrada e saída, sem precisar ler o código interno para adivinhar;

Segurança de tipos: O tipo dynamic desativa a verificação estática; passar tipos incorretos não gera erros de compilação e frequentemente causa falhas em tempo de execução;

Intellisense da IDE: Anotações de tipo ativam autocompletar e dicas de parâmetros no editor; sem tipos, a IDE não consegue mostrar sugestões precisas.

Quando posso omitir anotações de tipo?

Apenas recomendado para código privado local — funções usadas exclusivamente dentro do arquivo atual e nunca invocadas externamente.

Sintaxe curta de seta (=>)

Se o corpo da função (código dentro de {}) conter apenas uma única expressão de retorno, você pode usar a sintaxe de seta.

Exemplo

bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;Code language: PHP (php)
  • => expr equivale a { return expr; };
  • Apenas expressões podem ser escritas entre a seta e o ponto e vírgula; instruções como if são proibidas (use operadores ternários no lugar).
// Tabela de correspondência dos números atômicos dos gases nobres
final Map<int, String> _nobleGases = {
  2: 'Hélio',
  10: 'Neônio',
  18: 'Argônio',
  36: 'Criptônio',
  54: 'Xenônio',
  86: 'Rádon',
};

// Função curta de seta: retorna diretamente uma expressão em uma linha, equivalente a funções de bloco com return
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;

void main() {
  // Testar gases nobres existentes
  print(isNoble(2));   // true
  print(isNoble(18));  // true

  // Testar elementos comuns
  print(isNoble(6));   // false (Carbono)
  print(isNoble(99));  // false (nenhum elemento correspondente)
}Code language: PHP (php)

Parâmetros

Funções suportam parâmetros posicionais obrigatórios, seguidos de apenas uma das duas opções: parâmetros nomeados ou parâmetros posicionais opcionais — não podem ser misturados.

Vírgulas finais , são permitidas ao definir ou chamar parâmetros para melhorar a legibilidade do código.

1. Parâmetros nomeados Named parameters

Delimitados por {}, opcionais por padrão; adicione required para forçar a passagem obrigatória.

1) Parâmetros nomeados anuláveis básicos (sem valor padrão, o valor padrão é null, o tipo deve ser marcado com ? para ser anulável)

void enableFlags({bool? bold, bool? hidden}) {}
// Especificar explicitamente os nomes dos parâmetros na chamada
enableFlags(bold: true, hidden: false);
Code language: JavaScript (javascript)

Exemplo completo

/// Ativar flags de estilo de texto: negrito, oculto
void enableFlags({bool? bold, bool? hidden}) {
  print('Negrito: $bold, Oculto: $hidden');
}

void main() {
  // Passar todos os parâmetros nomeados
  enableFlags(bold: true, hidden: false);

  // Passar apenas um parâmetro nomeado, o outro fica null
  enableFlags(bold: true);

  // Passar apenas hidden
  enableFlags(hidden: true);

  // Não passar nenhum parâmetro, ambos os valores são null
  enableFlags();
}Code language: JavaScript (javascript)

Resultado da execução

D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Negrito: true, Oculto: false
Negrito: true, Oculto: null
Negrito: null, Oculto: true
Negrito: null, Oculto: nullCode language: JavaScript (javascript)

2) Definir valores padrão constantes em tempo de compilação (não precisa da marca de nulabilidade pois existe um valor padrão)

void enableFlags({bool bold = false, bool hidden = false}) {}
enableFlags(bold: true); // hidden usa automaticamente false
Code language: JavaScript (javascript)

Exemplo

/// Ativar flags de estilo de texto: negrito, oculto
void enableFlags({bool bold = false, bool hidden = false}) {
  print('Negrito: $bold, Oculto: $hidden');
}

void main() {
  enableFlags();//Sem parâmetros passados, ambos usam o valor padrão false → Negrito: false, Oculto: false
}Code language: JavaScript (javascript)

3) Parâmetros nomeados obrigatórios com required (Observação: Muito usado em construtores de componentes Flutter). O exemplo abaixo é código Flutter; saiba mais nos tutoriais de Flutter.

const Scrollbar({super.key, required Widget child});
// Parâmetros required também aceitam tipos anuláveis
const Scrollbar({super.key, required Widget? child});
Code language: JavaScript (javascript)

Dart não obriga a colocar parâmetros nomeados no final da lista; eles podem ser inseridos em qualquer posição da lista de parâmetros

repeat(times: 2, () {})Code language: CSS (css)
2. Parâmetros posicionais opcionais Optional positional parameters

Delimitados por [], valem null se omitidos; valores padrão constantes podem ser definidos.

// Sem valor padrão, tipo marcado com ?
String say(String from, String msg, &#91;String? device]) {
  var result = '$from says $msg';
  if (device != null) result = '$result with a $device';
  return result;
}
assert(say('Bob', 'Howdy') == 'Bob says Howdy');
assert(say('Bob', 'Howdy', 'smoke signal') == 'Bob says Howdy with a smoke signal');
Code language: PHP (php)

Exemplo completo

// [String? device] parâmetro posicional opcional sem valor padrão, vale null se omitido
String say(String from, String msg, [String? device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device'; //Adicionar informações do dispositivo à frase se device não for null
  }
  return result;
}

void main() {
  // Omitir o terceiro parâmetro opcional
  String res1 = say('Bob', 'Howdy');
  print(res1);

  // Passar o terceiro parâmetro posicional opcional
  String res2 = say('Bob', 'Howdy', 'smoke signal');
  print(res2);

  // Passar manualmente null para o parâmetro opcional
  String res3 = say('Alice', 'Hi', null);
  print(res3);
}Code language: JavaScript (javascript)

Definir valores padrão:

String say(String from, String msg, &#91;String device = 'carrier pigeon']) {
  return '$from says $msg with a $device';
}
assert(say('Bob', 'Howdy') == 'Bob says Howdy with a carrier pigeon');
Code language: PHP (php)

Exemplo completo

// Parâmetro posicional opcional com valor padrão carrier pigeon (pombo mensageiro)
String say(String from, String msg, [String device = 'carrier pigeon']) {
  return '$from says $msg with a $device';
}

void main() {
  // Omitir o terceiro parâmetro opcional, usa automaticamente o valor padrão carrier pigeon
  String res1 = say('Bob', 'Howdy');
  print(res1); //Bob says Howdy with a carrier pigeon

  // Passar dispositivo personalizado para sobrescrever o valor padrão
  String res2 = say('Bob', 'Howdy', 'smoke signal');
  print(res2); //Bob says Howdy with a smoke signal

  String res3 = say('Alice', 'Hello', 'mobile phone');
  print(res3); // Alice says Hello with a mobile phone

  String res4 = say('Jack', 'Tom', 'website foxdevelop.com');
  print(res4); // Jack says Tom with a website foxdevelop.com
}Code language: JavaScript (javascript)

Resultado da execução

Built firstdart:firstdart.
Bob says Howdy with a carrier pigeon
Bob says Howdy with a smoke signal
Alice says Hello with a mobile phone
Jack says Tom with a website foxdevelop.comCode language: JavaScript (javascript)


Função de ponto de entrada main ()

Todo programa Dart precisa de uma função main() de nível superior; ela é o único ponto de entrada de execução do programa.

  1. Versão básica sem parâmetros
void main() {
  print('Hello, welcome to foxdevelop.com!');
}
Code language: JavaScript (javascript)
Hello, welcome to foxdevelop.com!Code language: CSS (css)
  1. Programa de linha de comando recebendo argumentos de inicialização
// Comando de execução: dart run firstdart.dart 1 test
void main(List&lt;String> arguments) {
  print(arguments); // &#91;1, test]
}
Code language: JavaScript (javascript)

Use a biblioteca oficial args para análise complexa de argumentos de linha de comando.

Substitua firstdart.dart acima pelo nome do seu arquivo Dart


Funções como objetos de primeira classe First-class objects

1. Passar funções como parâmetros

void printElement(int element) =&gt; print(element);
var list = &#91;1, 2, 3];
list.forEach(printElement); // Passar a função diretamente
Code language: PHP (php)

Exemplo completo

void main() {
    void printElement(int element) => print(element);
    var list = [1, 2, 3];
    list.forEach(printElement); // Passar a função diretamente
}Code language: PHP (php)

Saída

1
2
3

2. Atribuir funções anônimas a variáveis

void main() {
    var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
    print(loudify('hello')); //!!! HELLO !!! 
}Code language: JavaScript (javascript)

Tipos de função Function Type

Você pode declarar explicitamente os tipos de variáveis de função

Formato: TipoRetorno Function(ListaParametros, {ParametrosNomeados})

void greet(String name, {String greeting = 'Hello'}) =&gt; print('$greeting $name!');
// Declarar variável de tipo função
void Function(String, {String greeting}) g = greet;
g('Dash', greeting: 'Howdy');
Code language: JavaScript (javascript)

Use typedef para criar aliases de tipos de função, melhorar a reutilização e legibilidade.

{String greeting}) → Um parâmetro nomeado greeting do tipo String

void main() {
    void greet(String name, {String greeting = 'Hello'}) => print('$greeting $name!');
    // Declarar variável de tipo função
    void Function(String, {String greeting}) g = greet;
    g('Jack', greeting: 'Howdy');
}Code language: JavaScript (javascript)

Saída

Howdy Jack!

Funções anônimas (Lambda / Closure fechamento léxico)

Funções sem nome definido, duas formas de escrita:

  1. Sintaxe de bloco (várias linhas)
void main() {
    const list = ['apples', 'bananas'];
    var uppercaseList = list.map((item) {
      return item.toUpperCase();
    }).toList();
    print(uppercaseList);
}Code language: PHP (php)

(item) { return item.toUpperCase(); } no código anterior é uma função anônima (lambda)

Saída: [APPLES, BANANAS]

  1. Abreviatura de seta (expressão de uma única linha)
void main() {
    const list = &#91;'fox', 'develop','foxdevelop.com'];
    var uppercaseList = list.map((item) => item.toUpperCase()).toList();
    uppercaseList.forEach((item) => print('$item: ${item.length}'));
}
Code language: PHP (php)

Saída

FOX: 3
DEVELOP: 7
FOXDEVELOP.COM: 14Code language: HTTP (http)

Escopo léxico Lexical scope

Dart usa um escopo léxico estático: o escopo de uma variável é definido pela hierarquia de chaves do código, e os escopos internos podem acessar todas as variáveis dos escopos externos.

bool topLevel = true;
void main() {
  var insideMain = true;
  void myFunction() {
    var insideFunction = true;
    void nestedFunction() {
      var insideNestedFunction = true;
      // Todos acessíveis
      assert(topLevel &amp;&amp; insideMain &amp;&amp; insideFunction &amp;&amp; insideNestedFunction);
    }
  }
}
Code language: JavaScript (javascript)

Fechamentos léxicos Lexical closures

Fechamento: um objeto função pode capturar e conservar variáveis do escopo externo, e acessá-las mesmo depois de sair do escopo original.

Function makeAdder(int addBy) {
  // Capturar variável externa addBy
  return (int i) =&gt; addBy + i;
}

void main() {
  var add2 = makeAdder(2);
  var add4 = makeAdder(4);
  assert(add2(3) == 5);
  assert(add4(3) == 7);
}
Code language: PHP (php)

Desglose passo a passo do fluxo de execução anterior

Passo 1: var add2 = makeAdder(2);

  1. Executar makeAdder, passar addBy = 2
  2. Criar função anônima: (int i) => 2 + i
  3. Atribuir essa função à variável add2. Nesse momento add2 é um objeto função cujo corpo é (int i) => 2 + i; recebe um inteiro i e retorna i+2
  4. A execução da função makeAdder finaliza, mas a função anônima lembra permanentemente addBy=2

Passo 2: var add4 = makeAdder(4);

  1. Executar makeAdder novamente, passar addBy = 4
  2. Criar uma nova função anônima totalmente independente: (int i) => 4 + i
  3. Atribuir a add4, que armazena sua própria cópia independente de addBy=4 sem interferir com add2. Ou seja, o valor addBy é guardado separadamente nos dois objetos função add2 e add4, um guarda 2 e o outro 4
  • A chamada a makeAdder(2) gera um fechamento independente com um valor vinculado único addBy = 2, atribuído a add2;
  • A chamada a makeAdder(4) gera um fechamento totalmente novo e separado com um valor vinculado único addBy = 4, atribuído a add4;
  • add2 e add4 são objetos função completamente separados, cada um armazena em privado sua variável addBy capturada sem interferir mutuamente.

Passo 3: Invocar add2(3)

Executar função interna: 2 + 3 = 5, a asserção se cumpre

Passo 4: Invocar add4(3)

Executar função interna: 4 + 3 = 7, a asserção se cumpre

Tear-offs de função

Se invocar uma função/método sem parênteses, cria-se um tear-off (fechamento leve), que substitui as lambdas anônimas escritas manualmente para um código mais limpo.

Esta é a sintaxe recomendada; basta passar a função diretamente.

var charCodes = &#91;68, 97, 114, 116];
var buffer = StringBuffer();
charCodes.forEach(print); // Tear-off de função
charCodes.forEach(buffer.write); // Tear-off de método
Code language: PHP (php)

Sintaxe equivalente mais longa

charCodes.forEach((code) =&gt; print(code));
charCodes.forEach((code) =&gt; buffer.write(code));
Code language: PHP (php)

Verificação de igualdade de funções

  • Funções de nível superior, métodos estáticos: == retorna true se os nomes de função coincidirem exatamente;
  • Métodos de instância: apenas os tear-offs vinculados à mesma instância de objeto são considerados iguais.
void foo() {}
class A {
  static void bar() {}
  void baz() {}
}
void main() {
  var x = foo;
  assert(foo == x);

  x = A.bar;
  assert(A.bar == x);

  var v = A(), w = A(), y = w;
  x = w.baz;
  assert(y.baz == x); // Mesma instância → iguais
  assert(v.baz != w.baz); // Instâncias diferentes → não iguais
}
Code language: JavaScript (javascript)

Valores de retorno Return values

  1. Todas as funções têm valor de retorno: se não houver um return explícito, é adicionado implicitamente return null; no final
foo() {}
assert(foo() == null);
Code language: JavaScript (javascript)
  1. Retornar vários valores: usar tuplas Record
(String, int) foo() {
  return ('something', 42);
}
Code language: JavaScript (javascript)

Acessores Getter & Setter

Ler ou atribuir qualquer propriedade equivale fundamentalmente a chamar seu getter ou setter; as variáveis normais geram automaticamente acessores implícitos, também é possível defini-los explicitamente à mão.

Vantagem: o código externo acessa uniformemente com .nomePropriedade, a lógica interna pode ser modificada em qualquer momento sem atualizar o código chamante externo.

String _secret = 'Hello';

// Getter para leitura
String get secret {
  print('Getter invocado');
  return _secret.toUpperCase();
}

// Setter para atribuições
set secret(String newMsg) {
  print('Setter invocado');
  if (newMsg.isNotEmpty) _secret = newMsg;
}

void main() {
  print(secret); // Leitura, ativa getter → HELLO
  secret = 'Dart is fun'; // Atribuição, ativa setter
  print(secret); // DART IS FUN
}
Code language: JavaScript (javascript)

* Geradores Generators

Geram sequências de forma diferida sob demanda, duas variantes: síncrono e assíncrono, usam yield para emitir valores.

  1. Gerador síncrono sync*, retorna Iterable
Iterable&lt;int> naturalsTo(int n) sync* {
  int k = 0;
  while (k &lt; n) yield k++;
}
Code language: HTML, XML (xml)
  1. Gerador assíncrono async*, retorna Stream
Stream&lt;int> asyncNaturalsTo(int n) async* {
  int k = 0;
  while (k &lt; n) yield k++;
}
Code language: JavaScript (javascript)
  1. Otimização de geradores recursivos yield* (delega a outro gerador para melhorar o desempenho)
Iterable&lt;int> naturalsDownFrom(int n) sync* {
  if (n &gt; 0) {
    yield n;
    yield* naturalsDownFrom(n - 1);
  }
}
Code language: HTML, XML (xml)

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *